用好setData 性能不再卡
随着小程序生态的蓬勃发展,多样化的用户需求推动更丰富的小程序功能。小程序承载更多的能力,伴随着更高的性能要求。无论是启动性能,还是运行性能,都会对用户体验产生影响,最终影响业务发展。
开发者可以通过 按需注入、分包异步 等方式来优化启动性能。针对运行性能优化,合理使用 setData 是重要一环,离不开其中 2 个重要方式:
减小每次 setData 的数据体积
控制调用 setData 频率
优化diff算法 减小数据体积
通过 setData 之前 diff 来减小数据体积 将不需要渲染到 wxml 的数据从 data 转移到其他地方存储
if (currentType != ARRAYTYPE && currentType != OBJECTTYPE) {// 基本类型直接对比if (currentValue !== previous[key]) {setResult(result, concatPathAndKey(path, key), currentValue);}} else if (currentType == ARRAYTYPE) {// 处理数组if (preType != ARRAYTYPE) {// 类型不符直接使用新数据setResult(result, concatPathAndKey(path, key), currentValue);} else {// 数组长度不符直接使用新数据if (currentValue.length < preValue.length) {setResult(result, concatPathAndKey(path, key), currentValue);} else {// 其他情况递归每个数组元素currentValue.forEach((item, index) => {_diff(item,preValue[index],concatPathAndKey(path, key) + '[' + index + ']',result,);});}}} else if (currentType == OBJECTTYPE) {if (preType != OBJECTTYPE ||Object.keys(currentValue).length < Object.keys(preValue).length) {// 对象同样先对比类型和长度,不符直接使用新对象setResult(result, concatPathAndKey(path, key), currentValue);} else {// 否则递归对象中的每个元素for (const subKey in currentValue) {const realPath =concatPathAndKey(path, key) +(subKey.includes('.') ? `["${subKey}"]` : `.${subKey}`);_diff(currentValue[subKey], preValue[subKey], realPath, result);}}
if (JSON.stringify(currentValue) === JSON.stringify(previous[key])) {continue;}
合并setData 控制调用频率
由于每次 setData 都会触发逻辑层虚拟 DOM 树的遍历和更新,可能导致触发完整的页面渲染流程。因此,建议开发者将一个同步时间片里面的 setData 合并为一个,在下一个时间片执行 setData,减少对象遍历以及完整渲染的工作。
performUpdate() {// 已经执行过不再执行if (Object.keys(this.dataMap).length === 0) {return;}// 一个时间片内执行一次,执行后清除数据this.oriSetData(this.dataMap, () => {// 依次执行callbackthis.callbackQueue.forEach(callback => {if (typeof callback === 'function') {callback();}});this.callbackQueue = [];});this.dataMap = {};}enqueueUpdate() {this.oriSetData = this.setData;this.setData = (data, callback) => {// 保存并合并datathis.dataMap = Object.assign(this.dataMap, data);// 保存callbackthis.callbackQueue.push(callback);wx.nextTick(() => {this.performUpdate();});};}
合理使用 setData 能够有效优化小程序运行性能,其中通过 diff 算法减小数据体积以及合并 setData 来控制调用频率 2 种方法减少 setData 耗时 22%,成功优化小程序性能体验。更多性能优化干货内容,欢迎点击 性能优化指南 了解。