微信小程序 ---- 虚拟列表
2022-09-26 本文已影响0人
牛会骑自行车
上篇也对列表的渲染做了一定的优化,不会一次性set太多的data,不过还没有达到渲染不卡顿的目的。还有分享过一个关于小程序性能的文档,这篇的主要目的是解决第六个问题
所以从根上减少性能耗费就需要减少页面需要渲染的节点数。
思路:
1.获取最外层容器的高度
2.设置item高度
3.计算每屏可以放置几个item
4.拼接上下需要补足的区域
5.原本只需要取出屏幕展示区域的数据就好,但是上下滑动速度快时会出现来不及渲染的情况。为避免这种情况,需要在显示区域的上下都再加一部分数据。相当于展示每屏需要获取上中下三屏的数据。
6.插播一则小知识。。。。关于wxs我好奇了很久,这次有空终于好好看了看,emmmm我的理解总结起来就是:不要太依赖这个东西(虽说也没什么好依赖的😂),暂时把它当过滤器就好,用法依照VUE里的computed就成~据说IOS可以快多少多少倍来着
上代码😊
wxml就按照图中所示给出容器就好 ⬇️
<wxs module="computed">
var paddingTop = function(startIndex, itemHeight) {
return startIndex * itemHeight * 2;
}
var paddingBottom = function(initData, endIndex, itemHeight) {
return (initData.length - endIndex) * itemHeight * 2;
}
module.exports = {
paddingTop: paddingTop,
paddingBottom: paddingBottom
}
</wxs>
<!-- 容器高度需要撑起来,height为100% -->
<!-- 这个容器是为了将来抽组件方便,如果长列表用在一整个页面且不是组件的话,则不需要这个容器 -->
<view class="container h_100" id="container">
<!-- scroll-view需要高度,还需要scroll方法来捕捉滑动的动作 -->
<scroll-view class="scroll-container h_100" scroll-y scroll-with-animation enhanced bindscroll="handleScroll">
<view class="outer-container" style="padding-top: {{computed.paddingTop(startIndex, itemHeight)}}rpx;padding-bottom: {{computed.paddingBottom(initData, endIndex, itemHeight)}}rpx;">
<block wx:for="{{currentData}}" wx:key="index">
<!-- 每行的容器需要设置高度,方便计算每屏展示的数据条数 -->
<view class="list-item" style="height: {{itemHeight * 2}}rpx;line-height: {{itemHeight * 2}}rpx;">{{item}}</view>
</block>
</view>
</scroll-view>
</view>
js ⬇️
Page({
data: {
// 原始数据
initData: [],
// 当前数据
currentData: [],
// 容器高度
containerHeight: 0,
// 每行的高度
itemHeight: 40,
// 每屏展示数据的条数
showCount: 0
},
// 获取容器高度 ---- 设置showCount
counting() {
// 获取容器高度需要一点点时间,我们需要在获取到容器的高度之后再获取数据所以用了promise
return new Promise(resolve => {
let query = wx.createSelectorQuery();
query.select('#container').boundingClientRect(rect => {
let containerHeight = rect.height;
let showCount = Math.ceil(containerHeight / this.data.itemHeight);
this.setData({
showCount
})
resolve();
}).exec();
})
},
//获取数据
getList() {
let initData = [];
for (let i = 1; i <= 20000; i++) {
initData.push(i);
}
this.setData({
initData,
})
this.renderPage(0);
},
renderPage(scrollTop) {
// 根据scrollTop判断该展示哪一部分数据
let startIndex = Math.floor(scrollTop / this.data.itemHeight);
// showCount * 2 ---- 上滑速度太快造成的页面白屏
let endIndex = startIndex + this.data.showCount * 2;
if (endIndex > this.data.initData.length) {
endIndex = this.data.initData.length;
}
// 将startIndex往前推也是为了解决下拉列表速度过快导致的白屏问题
startIndex = startIndex <= this.data.showCount ? 0 : startIndex - this.data.showCount;
// 当前展示的数据
let currentData = this.data.initData.slice(startIndex, endIndex);
this.setData({
startIndex,
endIndex,
currentData
})
},
handleScroll(event) {
let scrollTop = event.detail.scrollTop;
this.renderPage(scrollTop);
},
onLoad(options) {
this.counting().then(() => {
this.getList()
});
},
})
tada~~~一个虚拟列表就完成啦