2022-07-14 固定条目高度的虚拟列表实现

基本思路:需要两个容器,外层容器高度固定,超出后滚动。每条数据高度固定,内层容器的高度=每条数据高度数据条数,每页显示条数=外层容器高度/每条数据高度,监听外层容器的滚动事件,根据scrollTop来确定可视区域内起止数据在总数据的索引值,每条数据对应的元素设置绝对定位,top=索引值每条数据高度。为防止滑动过快产生空白,需要设置缓冲条数。

<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之间的数据 -->
        <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,//可视区域显示条数
            liHeight:30,//每条数据高度,假设是30
            bufferSize:20,//缓冲条数
            outerBoxHeight:300,//外层容器高度,假设是300  
            startIndex:0,//可视区域起始数据索引
            endIndex:0,  //可视区域截止数据索引
        }
    },
    mounted() {
        //假设有10000条数据
        for(let i=0;i<10000;i++){
            this.list.push({title:'数据-'+(i+1)})
        }
        // 每页显示条数=外层容器高度/每条数据高度
        this.size=Math.round(this.outerBoxHeight/this.liHeight)
        
    },
    methods: {
        onScroll(e){
          //滚动高度
          const {scrollTop}=e.target
          //当前第一条数据索引值=滚动高度/每条数据高度 
          const currentIndex=Math.floor(scrollTop/this.liHeight)
          //可视区域起始数据索引  从0和当前索引-缓冲条数中取大值
          this.startIndex=Math.max(0,currentIndex-this.bufferSize)
          //可视区域截止数据索引  从最大索引和当前索引+缓冲条数中取小值
          this.endIndex=Math.min(this.list.length-1,currentIndex+this.bufferSize)

        }
    },
}
</script>
image.png
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容