二、setData 优化
我们知道,与传统的浏览器 Web 页面最大区别在于,小程序的是基于 双线程 模型的,在这种架构中,小程序的渲染层使用 WebView 作为渲染载体,而逻辑层则由独立的 JsCore 线程运行 JS 脚本,双方并不具备数据直接共享的通道,因此渲染层和逻辑层的通信要由 Native 的 JSBrigde 做中转。
每当小程序视图数据需要更新时,逻辑层会调用小程序宿主环境提供的 setData 方法将数据从逻辑层传递到视图层,经过一系列渲染步骤之后完成 UI 视图更新。然而当 setData 传递大量的新数据、频繁的执行 setData 操作、过多的页面节点数时会影响渲染性能。
区分数据类别
意思是, setData 只用来通知页面更新,只有需要通知页面更新的时候,页面引用了某个 data 字段时才使用,其它字段数据我们有时候可能只是为了让 js 方便使用。比如如下数据
data: {form: {name:'xxxx', ... ... },index:0}
假如 页面上根本没用到 index 来展示,只是我们的逻辑变量,那么我们在赋值的时候就直接 this.data.index = xxx 即可,不要用 setData 去赋值了。
合理利用局部更新
setData 是支持使用 数据路径 的方式对对象的局部字段进行更新,我们可能会遇到这样的场景: list 列表是从后台获取的数据,并展示在页面上,当 list 列表的第一项数据的 src 字段需要更新时,一般情况下我们会从后台获取新的 list 列表,执行 setData 更新整个 list 列表。
// 后台获取列表数据constlist = requestSync();// 更新整个列表this.setData({ list });
实际上,只有个别字段需要更新时,我们可以这么写来避免整个 list 列表更新:
// 后台获取列表数据constlist = requestSync();// 局部更新列表this.setData({"list[0].src": list[0].src,});
善用自定义组件
小程序自定义组件的实现是由小程序官方设计的 Exparser 框架所支持,框架实现的自定义组件的组件模型与 Web Components 标准的 Shadow DOM 相似:
在页面引用自定义组件后,当初始化页面时,Exparser 会在创建页面实例的同时,也会根据自定义组件的注册信息进行组件实例化,然后根据组件自带的 data 数据和组件 WXML,构造出独立的 Shadow Tree ,并追加到页面 Composed Tree 。创建出来的 Shadow Tree 拥有着自己独立的逻辑空间、数据、样式环境及 setData 调用,这是组件化带来的好处。
基于自定义组件的 Shadow DOM 模型设计,我们可以将页面中一些需要高频执行 setData 更新的功能模块(如倒计时、进度条等)封装成自定义组件嵌入到页面中。当这些自定义组件视图需要更新时,执行的是组件自己的 setData ,新旧节点树的对比计算和渲染树的更新都只限于组件内有限的节点数量,有效降低渲染时间开销。