setData 应只用来进行渲染相关的数据更新。用 setData 的方式更新渲染无关的字段,会触发额外的渲染流程,或者增加传输的数据量,影响渲染耗时。
- ✅ 页面或组件的 data 字段,应用来存放和页面或组件渲染相关的数据(即直接在 wxml 中出现的字段);
- ✅ 页面或组件渲染间接相关的数据可以设置为「纯数据字段」,可以使用 setData 设置并使用 observers 监听变化;
- ✅ 页面或组件渲染无关的数据,应挂在非 data 的字段下,如
this.userData = {userId: 'xxx'}
; - ❌ 避免在 data 中包含渲染无关的业务数据;
- ❌ 避免使用 data 在页面或组件方法间进行数据共享;
- ❌ 避免滥用 纯数据字段 来保存可以使用非 data 字段保存的数据。
3.2 控制 setData 的频率
每次 setData 都会触发逻辑层虚拟 DOM 树的遍历和更新,也可能会导致触发一次完整的页面渲染流程。过于频繁(毫秒级)的调用 setData
,会导致以下后果:
- 逻辑层 JS 线程持续繁忙,无法正常响应用户操作的事件,也无法正常完成页面切换;
- 视图层 JS 线程持续处于忙碌状态,逻辑层 -> 视图层通信耗时上升,视图层收到消息的延时较高,渲染出现明显延迟;
- 视图层无法及时响应用户操作,用户滑动页面时感到明显卡顿,操作反馈延迟,用户操作事件无法及时传递到逻辑层,逻辑层亦无法及时将操作处理结果及时传递到视图层。
因此,开发者在调用 setData 时要注意:
- ✅ 仅在需要进行页面内容更新时调用 setData;
- ✅ 对连续的 setData 调用尽可能的进行合并;
- ❌ 避免不必要的 setData;
- ❌ 避免以过高的频率持续调用 setData,例如毫秒级的倒计时;
- ❌ 避免在 onPageScroll 回调中每次都调用 setData。
let item = e.currentTarget.dataset.item;
item.status = !item.status
let setListItems = {}
for (let i = 0; i < this.data.list.length; i++) {
let listItem = this.data.list[i];
if (listItem?.id === item.id) {
setListItems = Object.assign({ [`list[${i}].status`]: item.status }, setListItems)
}
}
var arr = Object.keys(setListItems);
if (arr.length > 0) {
this.setData(setListItems);
}
console.log(this.data.list)