1. 数据绑定
小程序的逻辑层和渲染层是分开的两个线程. 在渲染层, 宿主环境会把 WXML 转化成对应的 JS 对象, 在逻辑层发生数据变更的时候, 我们需要通过宿主环境提供的 setData 方法把数据从逻辑层传递到渲染层, 再经过对比前后差异, 把差异应用在原来的 Dom 树上, 渲染出正确的 UI 界面.
通过 setData 把 msg 数据从 "Hello World" 变成 "Goodbye", 产生的 JS 对象对应的节点就会发生变化, 此时可以对比前后两个 JS 对象得到变化的部分, 然后把这个差异应用到原来的 Dom 树上, 从而达到更新 UI 的目的, 这就是 "数据驱动" 的原理.
小程序的渲染层和逻辑层分别在两个线程中运行, 所以 setData 传递数据实际是一个异步的过程, 所以 setData 的第二个参数是一个 callback 回调, 在这次 setData 对界面渲染完毕后触发.
setData 其一般调用格式是 setData(data, callback), 其中 data 是由多个 key: value 构成的 Object 对象.
还需注意:
直接修改 Page 实例的 this.data 而不调用 this.setData 是无法改变页面的状态的, 还会造成数据不一致.
由于 setData 是需要两个线程的一些通信消耗, 为了提高性能, 每次设置的数据不应超过 1024kB.
不要把 data 中的任意一项的 value 设为 undefined, 否则可能会有引起一些不可预料的 bug.
2. 渲染层与逻辑层
小程序的 JS 脚本是运行在 JsCore 的线程里, 小程序的每个页面各自有一个 webView 线程进行渲染, 所以小程序切换页面时, 小程序逻辑层的 JS 脚本运行上下文依旧在同一个 JsCore 线程中.
[注意] 所有页面的脚本逻辑都跑在同一个 JsCore 线程, 页面使用 setTimeout 或者 setInterval 的定时器, 然后跳转到其他页面时, 这些定时器并没有被清除, 需要开发者自己在页面离开的时候进行清理.
3. 生命周期 (onLoad, onShow, onReady, onHide, onUnload)
页面初次加载的时候, 微信客户端就会给 Page 实例派发 onLoad 事件, Page 构造器参数所定义的 onLoad 方法会被调用, onLoad 在页面没被销毁之前只会触发 1 次, 在 onLoad 的回调中, 可以获取当前页面所调用的打开参数 option, 关于打开参数我们放在这一节的最后再展开阐述.
页面显示之后, Page 构造器参数所定义的 onShow 方法会被调用, 一般从别的页面返回到当前页面时, 当前页的 onShow 方法都会被调用.
在页面初次渲染完成时, Page 构造器参数所定义的 onReady 方法会被调用, onReady 在页面没被销毁前只会触发 1 次, onReady 触发时, 表示页面已经准备妥当, 在逻辑层就可以和视图层进行交互了.
以上三个事件触发的时机是: onLoad 早于 onShow,onShow 早于 onReady.
页面不可见时, Page 构造器参数所定义的 onHide 方法会被调用, 这种情况会在使用 wx.navigateTo 切换到其他页面, 底部 tab 切换时触发.
当前页面使用 wx.redirectTo 或 wx.navigateBack 返回到其他页时, 当前页面会被微信客户端销毁回收, 此时 Page 构造器参数所定义的 onUnload 方法会被调用.
在列表页打开商品详情页时把商品的 id 传递过来, 详情页通过刚刚说的 onLoad 回调的参数 option 就可以拿到商品 id, 从而绘制出对应的商品, 代码如代码清单 3-9 所示.
- // pages/list/list.JS
- // 列表页使用 navigateTo 跳转到详情页
- wx.navigateTo({ url: 'pages/detail/detail?id=1&other=abc' })
- // pages/detail/detail.JS
- Page({
- onLoad: function(option) {
- console.log(option.id)
- console.log(option.other)
- }
- })
4. 用户行为
下拉刷新 onPullDownRefresh
监听用户下拉刷新事件, 需要在 App.JSON 的 Windows 选项中或页面配置 page.JSON 中设置 enablePullDownRefresh 为 true. 当处理完数据刷新后, wx.stopPullDownRefresh 可以停止当前页面的下拉刷新.
上拉触底 onReachBottom
监听用户上拉触底事件. 可以在 App.JSON 的 Windows 选项中或页面配置 page.JSON 中设置触发距离 onReachBottomDistance. 在触发距离内滑动期间, 本事件只会被触发一次.
页面滚动 onPageScroll
监听用户滑动页面事件, 参数为 Object, 包含 scrollTop 字段, 表示页面在垂直方向已滚动的距离 (单位 px).
用户转发 onShareAppMessage
只有定义了此事件处理函数, 右上角菜单才会显示 "转发" 按钮, 在用户点击转发按钮的时候会调用, 此事件需要 return 一个 Object, 包含 title 和 path 两个字段, 用于自定义转发内容, 如代码清单 3-13 所示.
- // page.JS
- Page({
- onShareAppMessage: function () {
- return {
- title: '自定义转发标题',
- path: '/page/user?id=123'
- }
- }
- })
5. 导航与 tabBar
使用 wx.navigateTo({ url: 'pageD' }) 可以往当前页面栈多推入一个 pageD, 此时页面栈变成 [ pageA, pageB, pageC, pageD ].
使用 wx.navigateBack() 可以退出当前页面栈的最顶上页面, 此时页面栈变成 [ pageA, pageB, pageC ].
使用 wx.redirectTo({ url: 'pageE' }) 是替换当前页变成 pageE, 此时页面栈变成 [ pageA, pageB, pageE ], 当页面栈到达 10 层没法再新增的时候, 往往就是使用 redirectTo 这个 API 进行页面跳转.
- {
- "tabBar": {
- "list": [
- { "text": "Tab1", "pagePath": "pageA" },
- { "text": "Tab1", "pagePath": "pageF" },
- { "text": "Tab1", "pagePath": "pageG" }
- ]
- }
- }
在上面的例子所在的页面栈中使用 wx.switchTab({ url: 'pageF' }), 此时原来的页面栈会被清空 (除了已经声明为 Tabbar 页 pageA 外, 其他页面会被销毁), 然后会切到 pageF 所在的 tab 页面, 页面栈变成 [ pageF ], 此时点击 Tab1 切回到 pageA 时, pageA 不会再触发 onLoad, 因为 pageA 没有被销毁.
[注意] wx.navigateTo 和 wx.redirectTo 只能打开非 TabBar 页面, wx.switchTab 只能打开 Tabbar 页面.
我们还可以使用 wx. reLaunch({ url: 'pageH' }) 重启小程序, 并且打开 pageH, 此时页面栈为 [ pageH ].
路由方式 | 触发时机 | 路由前页面生命周期 | 路由后页面生命周期 |
---|---|---|---|
初始化 | 小程序打开的第一个页面 | onLoad, onShow | |
打开新页面 调用 | API wx.navigateTo | onHide | onLoad, onShow |
页面重定向 调用 | API wx.redirectTo | onUnload | onLoad, onShow |
页面返回 调用 | API wx.navigateBack | onUnload | onShow |
Tab | 切换 调用 API wx.switchTab | 参考下表 | 参考下表 |
重启动 | 调用 API wx.reLaunch | onUnload | onLoad, onShow |
Tab 切换对应的生命周期 (以 A,B 页面为 Tabbar 页面, C 是从 A 页面打开的页面, D 页面是从 C 页面打开的页面为例)
当前页面 | 路由后页面 | 触发的生命周期(按顺序) |
---|---|---|
A | A | 无 |
A | B | A.onHide(), B.onLoad(), B.onShow() |
A | B(再次打开) | A.onHide(), B.onShow() |
C | A | C.onUnload(), A.onShow() |
C | B | C.onUnload(), B.onLoad(), B.onShow() |
D | B | D.onUnload(), C.onUnload(), B.onLoad(), B.onShow() |
D(从转发进入) | A | D.onUnload(), A.onLoad(), A.onShow() |
D(从转发进入) | B | D.onUnload(), B.onLoad(), B.onShow() |
来源: http://www.bubuko.com/infodetail-3086653.html