小程序多图列表性能优化的方法和步骤
写这篇文章的原因:最近遇到了一个公司小程序项目画面元素太多导致的性能问题。从小程序提供的性能检测面板分析,确定图片元素占用内存过多。
因为之前主要做桌面应用开发和原生app开发,所以没怎么关注手机图片的内存占用问题。既然这次遇到了,我就借此机会学习一下优化技巧。
是什么导致了性能问题
简单来说就是: DOM节点太多,图片节点太多
过多的DOM节点会造成更多的内存占用。按照微信小程序目前的限制,如果内存占用超过500M,就会出现堵塞甚至闪退的情况。如果列表中的节点没有图片标签,内存占用不会很明显,但是过多的DOM节点会增加页面渲染时间。但是当列表节点包含图片时,内存占用会迅速上升。
这两点怎么解决?
对于以上两点,我们有相应的优化思路
1.DOM节点太多。
对于无限加载的页面,列表中的每个元素都有大量子节点。当列表数量增加时,页面上的节点总数将急剧增加。以小红书的小程序为例。
从上图可以看出,这个页面是一个由多张卡片组成的列表页面。假设一张卡片的DOM子节点数为30,当列表元素加载到1000时,页面将有30 * 1000=30,000个DOM节点。小程序明显受不了(注:微信小程序建议节点总数不要超过:个1000)
我们应该怎么做才能减少节点的数量?
想法很简单。我们只能在用户当前屏幕和上下屏幕加载真实内容,使用空白节点占据其他用户暂时看不到的地方。经此处理后,实际有内容的卡片数量不超过5张,页面节点总数为: 5 * 30 995=1145。与之前的节点数相比,有了很大的提升。
让我们看看代码的实现
在编写代码之前,让我们整理一下所需的数据结构。
首先,这是一个列表页面。我们需要一个列表来保存页面上显示的数据。 showCards中只保存5个真实数据。数据的显示卡将被空对象填充。
我们还需要一个List来保存所有的真实数据,这样当用户滑动页面时,我们就可以得到要实时显示的卡片的真实数据。
页面({showcards : [],totalcards 3360 []})接下来,让我们编写页面布局部分:
视图wx : for=' { { show cards } } ' wx : key=' { { index } } '自定义组件数据-卡片-数据=' { { item } } '/自定义组件/视图这是简单的代码框架(这里省略了很多不影响理解的代码细节。
我们首先在不优化DOM节点的情况下实现代码逻辑。当页面滑动到底部时,推一张新卡以显示卡片,并通过setData更新页面。这样就实现了一个简单的、无限加载的下拉列表页面。
async OnReachBottom(){ const new cards=wait fetchNewCards();this . data . show cards . push(new cards);这个。setdata({ showcards 3360 this。数据。showcards})}。接下来,我们实现了优化DOM节点的代码逻辑。当用户滑动页面时(onScroll事件),我们将判断当前页面上每张卡片的位置。如果卡片在用户可见范围内的上下屏,则显示真实数据,否则会被与原卡片宽度和高度相同的空白占位符节点代替。
在Page的on Page滚动回调中,我们调用了recycling函数(注意这里应该对回调进行节流,否则频繁调用会导致页面闪烁)。让我们看看这个回收页面节点函数:的主要逻辑
在回调中,我们首先通过API :CreateSelectorQuery()获取每张卡片的位置信息。绑定小程序提供的客户端。
接下来,我们使用位置信息来确定是否显示卡片的真实数据。对于没有显示真实数据的卡片,我们需要保存它们的高度信息,以便在渲染页面时用高度信息填充页面。同时,我们给空卡片赋予了一个类型属性,方便我们在wxml中渲染时判断卡片类型。
async onscroll callback(){ try { const rect list=wait this . calccardsheight();this . recycle card(rect list);} catch(e){ console . error(e);} } calcfeedheeght(){返回新的Promise((解析,拒绝)={ this.createSelectorQuery()。选择所有(` . card `)。boundingClientRect(rect list={ resolve(rect list));}) .exec() }) },recycle card(rect list){ const newShowCards=[];for(设I=0;I this . data . show cards . length;I){ const rect=RECTLiST[I];if (rect Math.abs(rectList[i])。top - 0)页面高度* 2){ newshowcards . push({ type : '空卡',height: rectList[i]。底部矩形列表[i]。top });} else { const feed=TotalCards[I];newshowcards . push(feed);} } this . setdata({ showcards 3360 newShowCards });}接下来,我们需要相应地修改wxml布局文件:
view wx : for=' { { show cards } } ' wx : key=' { { index } } ' view wx:if='{{item.type==' empty-card ' } ' class=' card empty-card ' style=' height : { { item . height } } px '/view自定义组件wx : if=' { { item . type!=='空卡' }} '数据卡-数据=' {{item}}' class='读卡器-卡片'/自定义组件/视图。这样既可以解决DOM节点过多的问题,又不会最大程度的影响用户的体验。(虽然用户在快速上下滑动时还是会看到一些空白,但是大部分,
2.图片节点太多
通过上一步的优化,我们实际上已经大大减少了页面上加载的图片数量。然而,在某些情况下,我们列表中的每张卡片并不只有一张图片,有时我们的图片组件是一个swiper。我们假设每个swiper平均显示10张图片,那么如果我们显示5张卡片,就会有50个Image//节点。对于一些低端安卓机来说,这个开销还是会造成卡壳。
那么什么是好的优化方案呢?对于前面的问题,我们的优化思路是简化用户看不到的节点的显示。
同样,对于swiper控件,用户可以看到的是当前图片和左右滑动可以看到的图片。其他位置的图片可以简化显示。从下图可以看出,实际上只需要立即加载三张图片。(红色方框代表swiper组件的可视区域)
我们使用一个变量来记录当前swiper控件显示的图片的坐标: curIndex,然后修改wxml布局文件。代码逻辑很简单,就是通过判断当前Image节点的索引和swiper显示节点的索引之间的距离,大于2就不显示了。
经过这样的处理后,我们的每个swiper组件最多将有三个Image/node占用实际内存。
swiper-item wx : for=' { { images } } ' wx : key=' { { index } } ' view image class=' img ' mode=' width fix ' src=' http: { { index-curIndex 2 index-curIndex-2?item . URL : ' ' } } '/image/view/wiper-item终于
以上是我在这次性能优化中使用的一些技巧,希望能给大家带来一些帮助。
如果你对我的文章感兴趣,这里有一些我关于数据可视化和D3.js的文章欢迎来到叉星:
https://github.com/ssthouse/ssthouse-blog
以上就是本文的全部内容。希望对大家的学习有帮助,支持我们。
版权声明:小程序多图列表性能优化的方法和步骤是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。