基本思路:需要兩個容器,外層容器高度固定,超出后滾動。每條數(shù)據(jù)高度固定,內(nèi)層容器的高度=每條數(shù)據(jù)高度數(shù)據(jù)條數(shù),每頁顯示條數(shù)=外層容器高度/每條數(shù)據(jù)高度,監(jiān)聽外層容器的滾動事件,根據(jù)scrollTop來確定可視區(qū)域內(nèi)起止數(shù)據(jù)在總數(shù)據(jù)的索引值,每條數(shù)據(jù)對應(yīng)的元素設(shè)置絕對定位,top=索引值每條數(shù)據(jù)高度。為防止滑動過快產(chǎn)生空白,需要設(shè)置緩沖條數(shù)。
<template>
<div id="outerBox" @scroll="onScroll" :style="{height:`${outerBoxHeight}px`,width:'200px',border:`1px solid #000`,overflow:'auto'}">
<ul id="innerBox" :style="{position:'relative',height:`${liHeight*list.length}px`}">
<!-- 只展示startIndex和endIndex之間的數(shù)據(jù) -->
<li v-for="(item,index) in list" v-if="index>=startIndex && index<=endIndex" :style="{position:'absolute',top:`${index*liHeight}px`,left:0,width:'100%',height:`${liHeight}px`,lineHeight:`${liHeight}px`}">{{item.title}}</li>
</ul>
</div>
</template>
<script>
export default{
data() {
return {
list:[],//列表
size:0,//可視區(qū)域顯示條數(shù)
liHeight:30,//每條數(shù)據(jù)高度,假設(shè)是30
bufferSize:20,//緩沖條數(shù)
outerBoxHeight:300,//外層容器高度,假設(shè)是300
startIndex:0,//可視區(qū)域起始數(shù)據(jù)索引
endIndex:0, //可視區(qū)域截止數(shù)據(jù)索引
}
},
mounted() {
//假設(shè)有10000條數(shù)據(jù)
for(let i=0;i<10000;i++){
this.list.push({title:'數(shù)據(jù)-'+(i+1)})
}
// 每頁顯示條數(shù)=外層容器高度/每條數(shù)據(jù)高度
this.size=Math.round(this.outerBoxHeight/this.liHeight)
},
methods: {
onScroll(e){
//滾動高度
const {scrollTop}=e.target
//當(dāng)前第一條數(shù)據(jù)索引值=滾動高度/每條數(shù)據(jù)高度
const currentIndex=Math.floor(scrollTop/this.liHeight)
//可視區(qū)域起始數(shù)據(jù)索引 從0和當(dāng)前索引-緩沖條數(shù)中取大值
this.startIndex=Math.max(0,currentIndex-this.bufferSize)
//可視區(qū)域截止數(shù)據(jù)索引 從最大索引和當(dāng)前索引+緩沖條數(shù)中取小值
this.endIndex=Math.min(this.list.length-1,currentIndex+this.bufferSize)
}
},
}
</script>

image.png