vue虚拟化列表封装

将下面代码复制一份到自己的项目中 

<template>
    <div class="scrollParent" ref="scrollContent" @scroll="handleScroll">
        <div :style="blankFillStyle">
            <div v-for="item,index in showDataList" :key="index">
                <slot :everyVirtual="item"></slot>
            </div>
        </div>
    </div>
</template>

<script>
export default {
    props:["oneHeight","virtualList"],
    data () {
        return {
            contentSize:"", //可视区域可以展示多少条数据
            startIndex:0, //记录当前滚动的第一个元素的索引
            currentScroll:0,  //记录当前滚动的距离
        }
    },
    methods:{
        // 获取可视区域可以展示多少条
        getContentSize(){
            // 两次取反可以获取到整数部分
            this.contentSize = ~~(this.$refs.scrollContent.offsetHeight / this.oneHeight) + 2;
        },
        // 监听滚动条
        handleScroll(){
            // 持续滚动  减少变量重新赋值  优化处理 只有在到下一个元素节点的时候才会重新给this.statrIndex赋值  避免和this.startIndex相关联的数据再次计算
            this.currentScroll = this.$refs.scrollContent.scrollTop;
            let currentIndex = ~~(this.$refs.scrollContent.scrollTop/this.oneHeight);
            if(this.startIndex == currentIndex){
                return
            }
            this.startIndex = currentIndex;
            if((this.startIndex + this.contentSize - 1)>this.virtualList.length-1){ //说明到达底部了
                this.$emit("scrollEnd")
            }
        }
    },
    activated(){
        this.$nextTick(()=>{
            this.$refs.scrollContent.scrollTop = this.currentScroll;
        })
    },
    computed:{
        endIndex(){ //获取最后一个元素的索引
            let endIndex = this.startIndex + this.contentSize*2;
            if(endIndex>this.virtualList.length-1){
                endIndex = this.virtualList.length-1
            }
            return endIndex;
        },
        showDataList(){
            let startIndex = 0;
            if(this.startIndex<=this.contentSize){
                startIndex = 0;
            }else{
                startIndex = this.startIndex - this.contentSize;
            }
            return this.virtualList.slice(startIndex,this.endIndex);
        },
        blankFillStyle(){
            let startIndex = 0;
            if(this.startIndex<=this.contentSize){
                startIndex = 0;
            }else{
                startIndex = this.startIndex - this.contentSize;
            }
            return{
                paddingTop:startIndex * this.oneHeight + "px",
                paddingBottom:(this.virtualList.length - this.endIndex) * this.oneHeight +"px"
            }
        }
    },
    mounted(){
        window.onresize = this.getContentSize();
        window.orientationchange = this.getContentSize();
    }
}
</script>

<style scoped>
    .scrollParent{
        height: 100%;
        width: 100%;
        overflow-y: auto;
    }
</style>

引入模块,调用模块

 <virtualScroll v-if="virtualList && virtualList.length"
         :oneHeight='40' 
         :virtualList='virtualList' 
         @scrollEnd='scrollEnd'
         v-slot:default="virtual">
        <div class="everyVirtual">{{virtual.everyVirtual}}</div>
 </virtualScroll>



oneHeight  每一个的高度
virtualList    请求拿到的数据列表
scrollEnd    滚动条滚动到底部的回调
<div class="everyVirtual">{{virtual.everyVirtual}}</div>    插槽、书写自己的每一个样式

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值