微信小程序开发:最容易忽略的5个致命细节(实战避坑指南)
摘要
开发微信小程序时,很多看似“理所当然”的写法,往往藏着大坑。setData到底是不是必须的?this指向为什么总是丢?onShow为什么莫名其妙触发?本文结合真实项目踩坑经验,总结5个最容易被忽略的细节,附带正确写法和代码示例,帮你少熬几个通宵。
1. setData:不是所有数据更新都需要它
很多新手被灌输“修改数据必须用setData”,这是错的。
正确认知
- 视图不需要更新时,直接用
this.data.a = 'xxx'修改,性能更好 - 视图需要更新时,才用
this.setData({ a: 'xxx' }) setData会触发视图重绘,频繁调用会导致页面卡顿,尽量合并数据一次性提交
定时器必须手动清理
Page({data:{count:0},timers:{},// 收集所有定时器startTimer(){this.timer1=setInterval(()=>{// 注意:这里改视图才用 setData,否则直接改 datathis.data.count++;},1000);},onUnload(){// 页面销毁时统一清理,防止内存泄漏clearInterval(this.timer1);}})2. this 指向:全部使用箭头函数
不要用function(){}定义任何回调函数,统一使用()=>{}。
错误写法(this 丢失)
wx.request({success:function(res){this.setData({list:res.data});// 报错!this 指向不对}})正确写法
wx.request({success:(res)=>{this.setData({list:res.data});// 箭头函数,this 正确指向页面}})原则:所有回调、定时器、监听器里的函数,一律用箭头函数,从此告别const that = this。
3. onLoad vs onShow:数据加载千万别放错地方
致命误区
很多人把数据请求写在onShow里,导致用户接电话、看短信、预览图片后返回页面,数据被重新加载,页面莫名其妙刷新,用户体验极差。
正确做法
- 首次数据加载→ 放
onLoad(只执行一次) - 从后台切回前台需要刷新→ 才放
onShow,但必须做防抖处理
Page({onLoad(options){// 首次加载,只执行一次this.fetchData();},onShow(){// 只有特定场景才刷新,比如订单状态变化// 不要在这里写 this.fetchData(),除非确实需要}})4. 组件传值:内部禁止直接修改 properties
错误认知
properties和data读写方式一样,所以可以在组件内部直接改properties。
后果
改了数据不会触发视图更新,且破坏单向数据流,导致数据混乱。
正确做法
子组件内部触发事件,父组件收到后自行修改数据并传回。
// 子组件Component({properties:{value:String},methods:{onChange(e){// 不直接 this.data.value = e.detailthis.triggerEvent('change',{value:e.detail});}}})<!-- 父组件 --><childvalue="{{val}}"bind:change="onChildChange"/>// 父组件Page({data:{val:''},onChildChange(e){this.setData({val:e.detail.value});}})5. observers:监听属性变化的神器
很多同学不知道observers的存在,却用手动watch或setTimeout轮询,效率极低。
用法
在组件中定义observers,监听某个data或properties的变化,自动执行逻辑。
Component({data:{a:1,b:2},observers:{'a':(val)=>{console.log('a 变为:',val);// 这里可以做额外操作,比如联动计算},'a, b':(aVal,bVal)=>{console.log('a 或 b 变化了');}}})6. wx:key:不写会出大问题
警告只是表象
不写wx:key不仅会有警告,更严重的是列表增删改后,渲染错位、输入框内容乱跳、动画异常等诡异问题。
正确写法
<!-- 单层列表 --><viewwx:for="{{list}}"wx:key="id">{{item.name}}</view><!-- 嵌套列表,内层必须重命名索引 --><viewwx:for="{{list}}"wx:for-index="idx"wx:key="idx"><viewwx:for="{{item.children}}"wx:for-index="childIdx"wx:key="childIdx">{{item.name}}</view></view>总结
| 问题 | 一句话解决方案 |
|---|---|
| setData 滥用 | 视图不变则用this.data.xxx = yy,视图要变才用setData |
| this 指向 | 全部使用()=>{},永远不用function(){} |
| 页面刷新混乱 | 首次加载放onLoad,onShow慎用 |
| 组件传值 | 内部不修改properties,用triggerEvent通知父组件 |
| 定时器泄漏 | onUnload清理所有定时器 |
| 列表渲染错乱 | 所有wx:for必须加wx:key |
最后一句:这些不是教科书理论,是我熬夜改 Bug 改出来的血泪教训。收藏本文,下次遇到诡异问题先对照查一遍,能省 80% 的调试时间。