更新时间:2019-09-09 15:18
与传统的 H5 应用不同,小程序运行架构分为 webview 和 worker 两个部分。webview 负责渲染,worker 则负责存储数据和执行业务逻辑。
evaluateJavascript
方式传输,数据大小会影响性能。首屏有多种定义,这里的首屏是指业务角度第一次有意义的渲染。比如: 对于列表页,首屏就是列表第一次渲染出的内容。
当用户访问一个小程序时,支付宝客户端会首先从 CDN 下载小程序资源包,所以资源包的大小会影响小程序启动性能。
优化建议:
部分小程序会在 onReady 中发出请求,导致首屏渲染延缓。
优化建议:将数据请求提前到 onLoad 中。
业务请求返回后,通常会调用 setData 触发页面重新渲染。执行过程如下:
由于 worker 与 webview 通信时,数据需要序列化,然后到了 webview 需要执行 evaluateJavascript
,因此如果一次性传输数据太大,会影响首屏渲染性能。
另外,如果 webview 上构造节点过多,层级嵌套太深(例如有的小程序列表页面一次性渲染超过 100 个列表项,每个列表项又有嵌套内容,而实际上整个屏幕可能只是显示不到 10 个),会导致差异比较时间较长,同时由于是首屏渲染,会一次性构造很多 DOM,影响首屏渲染性能。
优化建议:
$spliceData
将其他数据传输过去。任何页面变化都会触发 setData,同一时间可能会有多个 setData 触发页面进行重新渲染。如下四个接口都会触发 webview 页面重新渲染。
Page.prototype.setData
: 触发整个页面做差异比较Page.prototype.$spliceData
: 针对长列表做优化,避免每次传递整个列表,触发整个页面做差异比较Component.prototype.setData
: 只会从对应组件节点开始做差异比较Component.prototype.$spliceData
: 针对长列表做优化,避免每次传递整个列表,只会从对应组件节点开始做差异比较优化建议:
$spliceData
,不管是页面级别还是组件级别。在我们分析的案例中,有些页面有倒计时逻辑,但是有的倒计时过于频繁触发(ms 级别的触发)。$spliceData
, 将这一块封装成自定义组件,然后使用组件级别的 setData 或 $spliceData 触发组件重新渲染。$spliceData
多次追加数据,而不用传递整个列表。优化案例:
推荐指定路径设置数据:
this.setData({
'array[0]': 1,
'obj.x':2,
});
不推荐 如下用法(虽然拷贝了 this.data
, 仍然直接更改了其属性):
const array = this.data.array.concat();
array[0] = 1;
const obj={...this.data.obj};
obj.x=2;
this.setData({array,obj});
更不推荐 直接更改 this.data
(违反不可变数据原则):
this.data.array[0]=1;
this.data.obj.x=2;
this.setData(this.data)
长列表使用 $spliceData
:
this.$spliceData({ 'a.b': [1, 0, 5, 6] })
onPageScroll
事件,当事件触发时,需要通知对应组件重新渲染,此时的处理措施如下所示:
// /pages/index/index.js
Page({
onPageScroll(e) {
if (this.xxcomponent) {
this.xxcomponent.setData({
scrollTop: e.scrollTop
})
}
}
})
// /components/index/index.js
Component({
didMount(){
this.$page.xxcomponent = this;
}
})
可在组件的 didMount 中将组件挂载到对应的页面上,即可在页面中调用组件级别的 setData 只触发组件重新渲染。
在 for
中使用 key 来提高性能。
示例代码:
<view a:for="{{array}}" key="{{item.id}}"></view>
<block a:for="{{array}}"><view key="{{item.id}}"></view></block>
在文档使用中是否遇到以下问题
更多建议
匿名提交