![10a03ecb6ff403b3011cb5f80f0c5508.png](https://i-blog.csdnimg.cn/blog_migrate/84691ae8e108a44e3ddc3fb672e29e10.jpeg)
主要内容数据绑定、渲染、界面层数据渲染和事件处理。
![3bbc83b8192207acb091a109f0601b27.png](https://i-blog.csdnimg.cn/blog_migrate/26795963009f3cb952189e94b7e7dfea.jpeg)
一、数据绑定
1.1 渲染层和逻辑层
小程序宿主环境
我们称微信客户端给小程序所提供的环境为宿主环境。小程序借助宿主环境提供的能力,可以完成许多普通网页无法完成的功能。
小程序开发框架的目标是通过尽可能简单、高效的方式让开发者可以在微信中开发具有原生 APP 体验的服务。
整个小程序框架系统分为两部分:逻辑层(App Service)和 视图层(View)
逻辑层与渲染层分离
![98af8822671eb9ab58b40f7386f8e050.png](https://i-blog.csdnimg.cn/blog_migrate/2df2fb38b3b38d06bcf5b52370f30d35.jpeg)
首先,我们来简单了解下小程序的运行环境。小程序的运行环境分成渲染层和逻辑层,其中 WXML 模板和 WXSS 样式工作在渲染层,JS 脚本工作在逻辑层。
小程序的渲染层和逻辑层分别由2个线程管理:渲染层的界面使用了WebView 进行渲染;逻辑层采用JsCore线程运行JS脚本。一个小程序存在多个界面,所以渲染层存在多个 WebView线程,这两个线程的通信会经由微信客户端(下文中也会采用Native来代指微信客户端)做中转,逻辑层发送网络请求也经由Native转发,小程序的通信模型下图所示。
![b6895decb2f690e9aa5bbad3474a9934.png](https://i-blog.csdnimg.cn/blog_migrate/8db40b6ac01c4cce92813f0de1203692.jpeg)
1.2 逻辑文件介绍app.js pages.js
app.js 小程序逻辑
每个小程序都需要在 app.js 中调用 App 方法注册小程序实例,绑定生命周期回调函数、错误监听和页面不存在监听函数等
生命周期回调函数:小程序从创建到销毁的整个过程,自动创建的一些函数
包含内容:
- 全局变量 globalData:{}
- 生命周期函数
- 定义事件函数
pages.js 页面逻辑
对于小程序中的每个页面,都需要在页面对应的 js 文件中进行注册,指定页面的初始数据、生命周期回调、事件处理函数等
- data界面视图的数据内容
2.自己的生命周期函数
3.自定义事件的函数
1.3 逻辑层javascript
我们先看下小程序的javascript和普通页面的javascript区别
小程序javascript的三个特点:
1.小程序不是运行在浏览器中,没有BOM和DOM
console.log(window) ->undefined
console.log(document) ->undefined
2.小程序的js有一些额外的成员
App()方法 用于定义应用程序实例对象
Page()方法 用于定义页面对象
getApp()方法 用于获取全局的应用程序对象
wx 对象 提供核心API
// xxx.jsconst appInstance = getApp()
console.log(appInstance.globalData) // I am global data
3.小程序的js支持Commonjs规范
module.exports={} 导出
var data=require(./data.js) 引入
模块化
可以将一些公共的代码抽离成为一个单独的 js 文件,作为一个模块。模块通过 module.exports 对外暴露接口。
![c4619524a023e6e7758c78de9a9ab7ad.png](https://i-blog.csdnimg.cn/blog_migrate/dc6602181becdc521235dbeba425b607.jpeg)
在需要使用这些模块的文件中,使用 require 将公共代码引入
![cde56d6c4b31bb2218cfa34d529477e1.png](https://i-blog.csdnimg.cn/blog_migrate/82256d1233db934391cc8e71ca93d06d.jpeg)
在 JavaScript 文件中声明的变量和函数只在该文件中有效 不同的文件中可以声明相同名字的变量和函数,不会互相影响
1.4 界面层数据绑定
![8d8e4a7ef5b214a375c192053006986f.png](https://i-blog.csdnimg.cn/blog_migrate/0cb80f4c2cd02416b1bde986e8b9de43.png)
1.4.1 数据绑定
WXML 中的动态数据均来自对应 Page 的 data。
界面
逻辑
data
简单绑定
数据绑定使用 Mustache 语法(双大括号)将变量包起来,可以作用于:
内容
![21a6ef6cf48b58a8249a10ff849de1be.png](https://i-blog.csdnimg.cn/blog_migrate/71bb20e249f85e1ccca9d723b78b525c.jpeg)
组件属性(需要在双引号之内)
![eb09fcaf405059494b673422f5220ba4.png](https://i-blog.csdnimg.cn/blog_migrate/08fbac446bf25a55f4e9388f53fefb8d.jpeg)
{{}}语法用途
表达式 获取变量 绑定class属性
特殊地方:
![6e5b16abff44caeecf8aa38cc5b52542.png](https://i-blog.csdnimg.cn/blog_migrate/302931121ac9289fc4e09d20df565fea.png)
1.4.2 列表渲染
wx:for
在组件上使用 wx:for 控制属性绑定一个数组,即可使用数组中各项的数据重复渲染该组件。
默认数组的当前项的下标变量名默认为 index,数组当前项的变量名默认为 item
![dd62d73a18a3b7c53f100985c72ed8d9.png](https://i-blog.csdnimg.cn/blog_migrate/07d083142f102586a2594dc9c45c4f3f.jpeg)
使用 wx:for-item 可以指定数组当前元素的变量名,
使用 wx:for-index 可以指定数组当前下标的变量名:
![7c93e7b2308ca2149a14c6c9c42fbe36.png](https://i-blog.csdnimg.cn/blog_migrate/0abf97e1e2eebeba22945e68945b117f.jpeg)
类似 block wx:if,也可以将 wx:for 用在<block/>标签上,以渲染一个包含多节点的结构块。例如:
![51b94a4b8d2c09a6b4619c8d2403d13f.png](https://i-blog.csdnimg.cn/blog_migrate/19860765b79f7d31702cc547baf920fb.jpeg)
1.4.3 条件渲染
wx:if
在框架中,使用 wx:if="" 来判断是否需要渲染该代码块:
![f107ebaade1b3570a0bd56767ff5f8f6.png](https://i-blog.csdnimg.cn/blog_migrate/50f5d3e701d5b79dbd83251e2bd48110.jpeg)
因为 wx:if 是一个控制属性,需要将它添加到一个标签上。如果要一次性判断多个组件标签,可以使用一个 <block/> 标签将多个组件包装起来,并在上边使用 wx:if 控制属性。
![da309a35c75d122a565018e52a8320c4.png](https://i-blog.csdnimg.cn/blog_migrate/793967a16f0bdfc8ff4999b0e1cc8ea7.jpeg)
注意: <block/> 并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性。
wx:if vs hidden
因为 wx:if 之中的模板也可能包含数据绑定,所以当 wx:if 的条件值切换时,框架有一个局部渲染的过程,因为它会确保条件块在切换时销毁或重新渲染。
同时 wx:if 也是惰性的,如果在初始渲染条件为 false,框架什么也不做,在条件第一次变成真的时候才开始局部渲染。
相比之下,hidden 就简单的多,组件始终会被渲染,只是简单的控制显示与隐藏。
一般来说,wx:if 有更高的切换消耗而 hidden 有更高的初始渲染消耗。因此,如果需要频繁切换的情景下,用 hidden 更好,如果在运行时条件不大可能改变则 wx:if 较好。
二、事件处理
2.1 什么是事件
- 事件是视图层到逻辑层的通讯方式。
- 事件可以将用户的行为反馈到逻辑层进行处理。
- 事件可以绑定在组件上,当达到触发事件,就会执行逻辑层中对应的事件处理函数。
- 事件对象可以携带额外信息,如 id, dataset, touches
![b1762093d6933814e15938441215fdf1.png](https://i-blog.csdnimg.cn/blog_migrate/b1c8f67bf29b00b4fb9da39a0ce456fe.png)
事件的使用方式
在组件中绑定一个事件处理函数。
如bindtap,当用户点击该组件的时候会在该页面对应的Page中找到相应的事件处理函数。
<view id="tapTest" data-hi="WeChat" bindtap="tapName"> Click me! </view>
在相应的Page定义中写上相应的事件处理函数,参数是event。
![1b04aa04b7aa94213e8f2acb5c96e67a.png](https://i-blog.csdnimg.cn/blog_migrate/cda920eccfaa2eca8932f0e2c3384434.jpeg)
2.2 事件冒泡
2.2.1 事件分类
事件分为冒泡事件和非冒泡事件:
冒泡事件:当一个组件上的事件被触发后,该事件会向父节点传递。
非冒泡事件:当一个组件上的事件被触发后,该事件不会向父节点传递。
2.2.2 绑定并阻止事件冒泡
除 bind 外,也可以用 catch 来绑定事件。与 bind 不同, catch 会阻止事件向上冒泡。
例如在下边这个例子中,点击 inner view 会先后调用handleTap3和handleTap2(因为tap事件会冒泡到 middle view,而 middle view 阻止了 tap 事件冒泡,不再向父节点传递),点击 middle view 会触发handleTap2,点击 outer view 会触发handleTap1。
![f055446e8091e9a44879cad941c9bc33.png](https://i-blog.csdnimg.cn/blog_migrate/6850f4b58769c8891775658438bd929b.jpeg)
2.3 事件传参
dataset
在组件节点中可以附加一些自定义数据。这样,在事件中可以获取这些自定义的节点数据,用于事件的逻辑处理。
在 WXML 中,这些自定义数据以 data- 开头,多个单词由连字符 - 连接。这种写法中,连字符写法会转换成驼峰写法,而大写字符会自动转成小写字符。如:
- data-element-type ,最终会呈现为 event.currentTarget.dataset.elementType ;
- data-elementType ,最终会呈现为 event.currentTarget.dataset.elementtype 。
示例:
![e43526609949a4dd35fa803080ecc4f4.png](https://i-blog.csdnimg.cn/blog_migrate/79e7ba65f4ba0f31fca29abdf0c6e07d.jpeg)
2.4单数数据流
实现数据同步修改
index.wxml
![e013728cbf74c96e5f95cfdad24bdcda.png](https://i-blog.csdnimg.cn/blog_migrate/c02bdccaabd1383b911057f66117cdeb.png)
![3dbd98587543cf1d6930a315f9662e75.png](https://i-blog.csdnimg.cn/blog_migrate/8777dd4d122d928f1d9ab23411da6ac8.jpeg)
模板使用
WXML提供模板(template),可以在模板中定义代码片段,然后在不同的地方调用。
3.1 定义模板
使用 name 属性,作为模板的名字。然后在<template/>内定义代码片段,如:
![5fae9dd3ed4e7694404d680b4e26704b.png](https://i-blog.csdnimg.cn/blog_migrate/976c9a16eb289ad0e251a84842d57a94.jpeg)
3.2 使用模板
使用 is 属性,声明需要的使用的模板,然后将模板所需要的 data 传入,如:
![453ff8a1d0087bd6aebf75a77e3c0dce.png](https://i-blog.csdnimg.cn/blog_migrate/d34f4cc102220a370a529c37f46e7ba2.jpeg)
is 属性可以使用 Mustache 语法,来动态决定具体需要渲染哪个模板:
![663deb45683762b514878fce317575be.png](https://i-blog.csdnimg.cn/blog_migrate/b1632e27e5338efbed484fd726b40777.jpeg)
三、网易云精选案例
效果图:
![20954d103ebe13d73517011aa836bb6e.png](https://i-blog.csdnimg.cn/blog_migrate/37af479f04aa72dacff2689f8445a95b.jpeg)