大家好,我是Aliom252181,一个佛系且资质平平的前端coder。随着国内小程序生态的发展,相信各位前端coder或多或少都写过小程序,本文将简要叙述小程序开发常见的一些写法误区,并教大家如何写出一坨💩代码(不是)。
平平无奇的列表
某一天章三收到了一个需求,要求实现一个新闻列表。张三直接嘴一歪,大笔一挥定下了半天,说区区一个列表,半个小时写完还能摸🐟3个小时,岂不快哉!于是张三火速开始coding。
10分钟后,张三写好了,代码如下:
<scroll-view id="scroller" scroll-y lower-threshold='300'
bindscrolltolower='scrollToLower'>
<view wx:for="{{newsList}}" wx:for-item="itm" wx:for-index="idx" wx:key="idx">
<view class="newsItem">{{itm.title}}</view>
</view>
</view>
data: {
pageParams: {
pageNum : 1,
pageSize : 24
},
newsList:[]
},
onLoad(){
this.getNews();
},
async getNews() {
let {pageParams,newsList} = this.data;
let res = await Serv.getNews(pageParams);
if (res.data) {
newsList = [...newsList,...res.data.list]
pageParams.pageNum++;
this.setData({
newsList,
pageParams
})
} else{
console.error(res);
}
}
scrollToLower() {
this.getNews(this.data.pageParams);
}
我们能看到,张三定义了一个data参数,一个获取新闻的接口数据接受方法,一个触底加载方法。页面循环体该有的也都有了,一眼看上去没什么问题。
代码审核
这时张三的上级李四收到了审核通知,于是李四拉取了代码,准备检查方案。
减少不必要的标签嵌套
在不影响代码运行和可读性的前提下,尽量减少标签的嵌套,可以大幅的增加页面数据的列表条数,如果你的列表数据量有限,可以用这种方法来增加列表渲染条数。如果数据量很大,再怎么精简也超过2万的节点,这个方法则不适用。
解决方案
替换没有样式只起到循环作用的view
为block
,block
不会渲染出节点,可以提高有效渲染的条数。
<scroll-view id="scroller" scroll-y lower-threshold='300'
bindscrolltolower='scrollToLower'>
<block wx:for="{{newsList}}" wx:for-item="itm" wx:for-index="idx" wx:key="idx">
<view class="newsItem">{{itm.title}}</view>
</block>
</view>
可选链操作符
在getNews
方法中,张三直接用返回值的外层判断是否有值,如果在接口异常时data
并没有list
属性,那么这里就会有逻辑错误,下面的res.data.list
就会指向undefined
,阻断程序运行并报错。
解决方案
我们需要使用?.
来寻找参数。?.
可选链操作符,允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。操作符的功能类似于 . 链式操作符,不同之处在于,在引用为null
或undefined
的情况下不会引起错误。
if(res.data?.list)
请求开关
我们可以看到,在scroll-view
内的触底方法调用下,会直接调用获取下一页的问题,问题就处在这里,当前逻辑是距离底部300时触发scrolltolower
事件,如果请求返回很慢或者你的自定义加载逻辑用的是bindscroll
,就需要对请求触发进行控制,在上一个请求没有结束之前,不可以发起下一个请求。
解决方案
设置请求状态参数,请求时设置为true
,如果重复触发,外部读取到false
就不会执行接下来的代码。
setData
我们可以看到,赋值的时候张三全部用data下一级参数来赋值,但是他只修改了其中几个参数,这是有性能风险的。小程序setDate的性能会受到setData数据量大小和调用频率限制。所以要围绕减少每一次setData数据量大小,降低setData调用频率进行优化。
解决方案
删除冗余字段
后端的同事经常把数据从数据库中取出就直接返回给前端,不经过任何处理,所以会导致数据大量的冗余,很多字段根本用不到,我们需要把这些字段删除,减少setDate的数据大小。
正确使用setData
通常,我们对data
中数据的增删改操作,是把原来的数据取出,处理,然后用setData整体去更新,比如我们列表中使用到的上拉加载更多,需要往newsList
尾部添加数据:
这样会导致 setData
的数据量越来越大,页面也越来越卡。
newsList = [...newsList,...res.data.list]
this.setData({newsList})
我们可以对这样的数据进行如下操作。
let newsList=[{...},{...},{...},{...},{...},{...}];
let changeData={};
let index=this.data.newsList.length
newData.forEach((item) => {
// 赋值,索引递增
changeData['newsList[' + (index++) + ']'] = item;
})
this.setData(changeData)
当前张三本次的代码中不涉及数据修改,我们只需要把newsList
变成二维数组就好了,每次只更新newsList
的对应页面的一个list
,就不会出现全部setData
的问题。
if (res.data) {
pageParams.pageNum++;
this.setData({
'newsList[pageParams.pageNum]':res.data.list,
pageParams
})
}
如果数据量很大还需要考虑虚拟列表解决方案,因为渲染节点越多滚动的时候越卡,这时可以使用recycle-view长列表组件,当然也可以自行设计并实现虚拟列表。
写在最后
小程序这个系列我还会继续更新,敬请期待~
本篇文章到这里就结束了,如果文章对你有用,可以三连支持一下,如果文章中有错误或者说你有更好的见解,欢迎指正~
往期文章: