用于解决长列表dom渲染溢出造成的空白无法显示问题。
思路:借助scroll-view的scroll事件的事件对象中的scrollTop的值判断当前用户可视的第一个元素的index,用v-if控制当前可视元素的前10个item和后10个item渲染,其他的不渲染,达到局部渲染的效果,从而解决dom溢出的问题。item的作用是保留高度,使滚动条保持正常位置。
前提条件是list里面的item的height要一样,才能计算出当前可视的元素的index。
示意图如下:
1)不分页情况
html结构如下:
<scroll-view scroll-y="true" @scroll="scroll" :style="'height: 800rpx;background-color: #f0f0f6;'">
<view class="list">
<view class="item" v-for="(item,childIndex) in 100" :key="childIndex">
<view class="hide" v-if="currentItem - 10 < childIndex+1 && currentItem + 10 > childIndex+1">
123
</view>
</view>
</view>
</scroll-view>
scss样式如下:
.list{
.item{
height: 200rpx;
margin-bottom: 20rpx;
background-color: pink;
}
}
javascript代码如下:
data() {
return {
currentItem:1 // 默认当前可视的item元素是第一个
}
},
methods: {
scroll(e){
const itemHeight = 220/2 // 除以2是因为scrollTop的值单位是px,而元素高度的单位是rpx
this.currentItem = Math.floor(e.detail.scrollTop / itemHeight) + 1
}
}
效果如下:
2)分页情况
html结构如下:
<scroll-view scroll-y="true" @scroll="scroll" @scrolltolower="lower" :style="'height:800rpx;'" lower-threshold="100">
<view class="list">
<view :class="'page'+index" v-for="(page,index) in dataList" :key="index">
<view class="item" v-for="(item,childIndex) in page" :key="childIndex">
<view class="hide" v-if="currentPage-2 < index+1 && currentPage+2 > index+1">
123
</view>
</view>
</view>
</view>
</scroll-view>
scss样式如下:
.list{
.item{
height: 200rpx;
margin-bottom: 20rpx;
background-color: pink;
}
}
javascript代码如下:
data() {
return {
dataList:[],
currentPage:1,
page:1,
total:1122,
size:10
}
},
computed:{
isFinish(){
if(this.total !== 0 && this.page >= Math.ceil(this.total / this.size)){
return true
}
return false
},
},
methods: {
getData(){
// 发请求获取数据,此处仅为模拟。
let pageList = []
for(var i=0;i<this.size;i++){
pageList.push(i)
}
// 将请求数据插入数据列表,得到二维数组。
this.dataList.push(pageList)
},
scroll(e){
const pageHeight = this.size*220/2
this.currentPage = Math.floor(e.detail.scrollTop / pageHeight) + 1
},
lower(){
if(this.isFinish) {
return
}
this.page += 1
this.getData()
},
},
onLoad(){
this.getData() // 先加载第一页数据
}
效果如下:(当前第五页,则渲染第3,4,5页的数据,第1,2页的数据不渲染)