小程序长列表优化,解决数据过多白屏问题
场景: 使用mpvue框架,列表数据量过大
解决方法-分页渲染数据,列表滚动时将可视区域外元素数据清空只保留高度
先贴代码,有注释
html
<template>
<!--index.wxml-->
<div class="list-box">
<div
:id="'page'+pindex"
class="list-page"
:style="{height:pitem.height ? pitem.height+'px':'auto'}"
v-for="(pitem,pindex) in list"
:key="pindex"
>
<section v-if="pitem.length > 0">
<div class="list-item" v-for="(item,index) in pitem" :key="index">{{item}}</div>
</section>
</div>
</div>
</template>
js
<script>
export default {
data() {
return {
list: [],
page: 1,
pageNumber: 10,
allData: []
};
},
methods: {
loadData() {
// 先为dom渲染数据,才能在下面的dom数据获取中拿到dom数据
let data = [];
let oldDt = JSON.parse(JSON.stringify(this.list));
for (let i = 0; i < this.pageNumber; i++) {
data.push(1 + i + (this.page - 1) * this.pageNumber);
}
if (this.page == 1) {
this.list = [];
}
this.allData.push(data);
oldDt[this.page - 1] = data; //缓存数据,优化性能时使用
this.list = oldDt;
//计算并记录数据的边界值
this.boundings = Array.isArray(this.boundings) ? this.boundings : [];
let index = this.page - 1;
// 通过延迟的方式去获取dom数据
setTimeout(() => {
const query = wx.createSelectorQuery();
query
.select(`#page${index}`)
.boundingClientRect(rect => {
this.boundings[index] = {
height: rect.height, //高度
top:
index == 0
? rect.top
: this.boundings[index - 1].top +
this.boundings[index - 1].height, //上边界
bottom:
index == 0
? rect.bottom
: this.boundings[index - 1].bottom + rect.height //下边界
};
})
.exec();
wx.stopPullDownRefresh();
wx.hideLoading();
}, 1000);
}
},
onReady() {
this.loadData();
},
onUnload() {},
onPageScroll(e) {
//当前与滚动区域底部相交的元素索引
this.index = this.index ? this.index : 0;
this.windowHeight = this.windowHeight
? this.windowHeight
: wx.getSystemInfoSync().windowHeight;
this.boundings.forEach((item, index) => {
// 如果没有在屏幕中,并且视野的高度小于我的结尾位置距离顶部的距离,也就是说,这个dom是我正在查看的dom
if (
item.top < e.scrollTop + this.windowHeight &&
e.scrollTop + this.windowHeight <= item.bottom
) {
this.index = index;
}
});
//当前相交元素的前2后2元素显示,超出部分隐藏
let oldarr = JSON.parse(JSON.stringify(this.list));
oldarr.forEach((item, index) => {
// 这里的意思是渲染了三页的数据,并且list这一页有数据,并且数据是obj
if (
(index == this.index ||
index == this.index - 1 ||
index == this.index - 2 ||
index == this.index + 1 ||
index == this.index + 2) &&
oldarr[index] &&
!Array.isArray(oldarr[index])
) {
// 是的话就替换成我们的数组数据
oldarr[index] = this.allData[index];
}
// 这里是指当前索引页不是显示区域数据判断,并且数据类型是数组
if (
(index > this.index + 2 || index < this.index - 2) &&
Array.isArray(oldarr[index])
) {
// 是的话就替换成我们的dom高度数据
oldarr[index] = { height: this.boundings[index].height };
}
});
this.list = oldarr;
},
onPullDownRefresh() {
this.page = 1;
setTimeout(() => {
this.loadData();
}, 1000);
},
onReachBottom() {
this.page = ++this.page;
wx.showLoading();
setTimeout(() => {
this.loadData();
}, 1000);
}
};
</script>
less
<style lang="less" scoped>
.list-item {
height: 200rpx;
background: #ddd;
display: flex;
align-items: center;
justify-content: center;
border-bottom: 1px solid #fff;
}
</style>
有详细备注就不多说了。自己看代码啦。代码参考这位大佬的小程序原生代码,点击可跳转,大佬有小程序代码片段