我们怎么把拼团页的 setData 卡顿从1.2s压到120ms

我们怎么把拼团页的 setData 卡顿从1.2s压到120ms
去年给客户做拼团页,上线第三天崩溃率突然涨到17%,查了两天才发现是 setData 里写了 for 循环。
性能优化:setData 与长列表
性能问题总是最隐蔽。小程序架构是逻辑层和视图层分离的,每次 setData 都要走一遍 JSON 序列化,开销很大。

那个拼团页的问题出在商品详情页。用户快速滑动时,页面卡得不行。用开发者工具的 Performance 面板一抓,发现滚动事件触发了全量数据更新,主线程被频繁阻塞,UI 渲染严重滞后。
怎么修?三点措施:只更新必要字段(比如 this.setData({'list[0].name': 'newName'})),别全量替换;大量数据用分片加载或虚拟列表,别一次性塞进去;touchmove 这类高频事件必须节流,不能每帧都 setData。
后来引入了虚拟列表。实测滚动1000条商品时,内存峰值从120MB压到30MB,首屏渲染快了一倍多。
样式陷阱:rpx 与布局
小程序样式和 Web 不太一样,坑不少。
我之前做个支付表单,在不同真机上宽度和间距全部错位。排查很久才发现,布局里混用了 px 和 rpx,且样式嵌套过深。rpx 是按屏幕宽度换算的,不同分辨率设备表现会有差异,累积起来就炸了。
教训是:主要布局统一用 rpx;嵌套层级别超过三层;利用 page 或 component 选择器隔离样式。另外,border-box 模型虽然默认开启,但在老机型上可能有问题,重置样式时最好显式写上 box-sizing: border-box。
组件封装
组件封装不好,后期维护要命。
我封装通用表单组件时总结了三条原则:properties 要加 validate 校验,传 number 进来直接 console.warn 并 fallback;内部状态变更通过统一接口暴露,别让父组件直接操作子组件数据;父子组件别循环引用,否则容易加载死锁。
// components/my-component/index.js
Component({
properties: {
value: {
type: String,
value: '',
observer: 'onValueChange'
}
},
data: {
internalValue: ''
},
methods: {
onValueChange(newVal) {
this.setData({ internalValue: newVal });
},
handleChange(e) {
const { value } = e.detail;
this.setData({ value });
this.triggerEvent('change', { value });
}
}
});
排查技巧
遇到奇怪问题,我的排查顺序:先看开发者工具内存占用和 WXML 节点数,定位泄漏或膨胀;再看网络请求时序,避免重复请求;最后检查生命周期,确认 onLoad、onShow 里有没有资源没释放。
记得有一次页面切换卡顿,内存分析显示有泄漏。最终定位到一个异步回调里的 setTimeout 没清理,对象没法被垃圾回收。现在看到 setTimeout 就手抖。
本文首发于 我们怎么把拼团页的 setData 卡顿从1.2s压到120ms — https://lyxq.com.cn/zh/blog/miniprogram-development-pitfalls-guide
转载或引用请注明出处,商业使用请联系作者获得授权。