vue长列表,虚拟滚动

1.新建子组件,将数据传递过去(几万条数据的数组,一次性展示多少条,每条数据的行高).

复制代码
<template>
    <div class="vitualScroll">
        <sub-scroll :dataList="dataList" :rowCount="20" :rowHeight="20"></sub-scroll>
    </div>
</template>

<script>
import subScroll from "./components/subScroll.vue"
export default{
    name: 'virtualScroll',
    data(){
        return {
            //冻结数组,初步优化
            dataList: Object.freeze(new Array(20000).fill(null).map((item, index) => ({ n: index+1 })))
        }
    },
    components:{
        subScroll
    }
}
</script>
<style scoped lang="less">
.vitualScroll{
    width: 100%;
    height: 100%;
}
</style>

2.子组件subScroll.vue

div.scrollBar用来使父盒子出现滚动条,div.scrollBar的高度就是数据总条数*单条数据的高度。

div.list才是v-for数据的盒子,采用绝对定位,在父元素滑动事件中更新数据,并且将div.list的位置拉回来(div.list采用绝对定位,滑动滚动会往上跑)

复制代码
<template>
    <div class="scrollView" ref="scrollView" :style="{'--rowHeight': $props.rowHeight + 'px'}" @scroll="onScroll()">
        <div class="scrollBar" :style="{'--scrollBarHeight': $props.dataList.length * $props.rowHeight + 'px'}">

        </div>
        <div class="list" ref="list">
            <div class="item" v-for="(item, index) in copyDataList" :key="index">
                {{ item.n }}
            </div>
        </div>
    </div>
</template>

<script>
export default{
    name: 'subScroll',
    data(){
        return {
            start: 0
        }
    },
    computed:{
        copyDataList(){
            return this.$props.dataList.slice(this.start, this.$props.rowCount + this.start)
        }
    },
    props:{
        dataList: {
            type: Array,
            default(){
                return [{}]
            }
        },
        rowCount: {
            type: Number,
            default: 0
        },
        rowHeight: {
            type: Number,
            default: 0
        }
    },
    mounted(){
        
    },
    methods: {
        onScroll(){
            //全局节流函数
            this.$throttle(this.updataData, 50)
        },
        updataData(){
            let offsetTop = this.$refs.scrollView.scrollTop
            let offsetNum = Math.round(offsetTop / this.$props.rowHeight)
            this.start = offsetNum
            this.$refs.list.style.transform = `translateY(${offsetTop}px)`
            console.log('滑动的距离', offsetTop)

        }
    }
}
</script>

<style lang="less" scoped>
.scrollView{
    width: 200px;
    height: 400px;
    overflow: auto;
    position: relative;
    .item{
        height: var(--rowHeight);
    }
    .scrollBar{
        height: var(--scrollBarHeight);
    }
    .list{
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
    }
}
</style>
相关推荐
Zacks_xdc10 分钟前
【前端】使用Vercel部署前端项目,api转发到后端服务器
运维·服务器·前端·安全·react.js
尚学教辅学习资料10 分钟前
Ruoyi-vue-plus-5.x第五篇Spring框架核心技术:5.1 Spring Boot自动配置
vue.js·spring boot·spring
给月亮点灯|18 分钟前
Vue基础知识-脚手架开发-使用Axios发送异步请求+代理服务器解决前后端分离项目的跨域问题
前端·javascript·vue.js
叫我阿柒啊20 分钟前
从Java全栈到前端框架:一次真实的面试对话与技术解析
java·javascript·typescript·vue·springboot·react·前端开发
张迅之1 小时前
【React】Ant Design 5.x 实现tabs圆角及反圆角效果
前端·react.js·ant-design
@CLoudbays_Martin111 小时前
为什么动态视频业务内容不可以被CDN静态缓存?
java·运维·服务器·javascript·网络·python·php
蔗理苦2 小时前
2025-09-05 CSS3——盒子模型
前端·css·css3
二川bro3 小时前
第25节:VR基础与WebXR API入门
前端·3d·vr·threejs
上单带刀不带妹3 小时前
Node.js 的模块化规范是什么?CommonJS 和 ES6 模块有什么区别?
前端·node.js·es6·模块化
缘如风3 小时前
easyui 获取自定义的属性
前端·javascript·easyui