vue实现虚拟滚动(大数据、vue3)

大量数据渲染存在性能问题,解决方法之一(虚拟滚动)

  • 滚动定位三种(transform偏移、padding-top填充、absolute定位)
  • 示例paddingTop填充方法,剩余两种方法实现方式与其大致相同
<template>
    <div class="t-container">
        <div class="wrapper" ref="wrapper" @scroll="handleScroll">
            <div class="wrapper-scroll" :style="{height:`${wrapperScrollH}px`, paddingTop:`${paddingTop}px`}">
                <div v-for="item in showList" :key="item.index">
                    <span class="title">{{item.index}} 测试</span>
                    <ul>
                        <li class="test">就问你<span>大量数据<span>x</span></span></li>
                        <li class="test">卡不卡<span>虚拟滚动<span>z</span></span></li>
                        <li class="test">不知道<span>小案例<span>p</span></span></li>
                        <li class="test">真的吗<span>页面测试<span>就是玩</span></span></li>
                        <li class="test">{{item.content}}<span></span></li>
                    </ul>
                </div>
            </div>
        </div>
    </div>
</template>
<script>
import { reactive, ref, computed } from "@vue/composition-api"
export default {
    setup(props, context){
        // 子元素高度设置为150
        let arr = reactive([]);
        const wrapper = ref(null);
        let start = ref(0);
        let end = ref(10);
        // 滚动条滚动回调
        const handleScroll = (e)=>{
        	// 滚动条到容器顶部距离
            let top = e.srcElement.scrollTop;
            // 计算数据开始渲染下标,
            let iTop = parseInt(top / 150);
            // start 需要iTop - 5, 使页面更为流畅,往前多渲染5条数据
            start.value = iTop > 5 ? iTop - 5 : 0;
            // 未渲染数据,使用padding占位
            paddingTop.value = start.value * 150;
            // 计算数据结束渲染下标
            let iwTop = parseInt((top + wrapperH) / 150);
            // 往后多渲染5条数据,页面更为流畅
            end.value = iwTop + 5;
        };
        // 渲染10万条数据
        const total = 100000;
        for(let i = 0; i < total; i++){
            arr.push({
                index:i,
                content: i + "测试效果" + Math.random()
            });
        }
        // 计算需要渲染真实dom的数据
        const showList = computed(()=>{
            return [...arr.slice(start.value, end.value)]
        });
        let wrapperH = ref(0);
        let wrapperScrollH = ref(0);
        // 获取容器高度,与设置滚动区域高度
        onMounted(()=>{
            wrapperScrollH.value = arr.length * 150;
            wrapperH = wrapper.value.clientHeight;
        });
        let paddingTop = ref(0);
        return {
            arr,
            wrapper,
            handleScroll,
            showList,
            wrapperScrollH,
            wrapperH,
            paddingTop
        }
    }
}
</script>
<style scoped lang="stylus">
.t-container
    padding 20px
    background-color pink
    width 800px
    height 400px
    margin 10px auto
    >div
        margin 10px auto
    .wrapper
        height calc(100% - 40px)
        overflow auto 
        .wrapper-scroll
            display flex
            flex-direction column
            overflow hidden
        .title, .test
            line-height 20px
        li
            list-style none
            margin 5px 40px
</style>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值