vue实现虚拟滚动
虚拟滚动的基本概念
虚拟滚动(Virtual Scrolling)是一种优化长列表渲染性能的技术,通过仅渲染可视区域内的元素,减少DOM节点数量,从而提升页面性能。适用于数据量大的表格、列表等场景。
Vue实现虚拟滚动的核心步骤
1. 计算可视区域高度和元素高度
确定容器高度(clientHeight)和每个子项的高度(itemHeight),或动态计算不定高元素的尺寸。

2. 动态计算渲染范围
根据滚动位置(scrollTop)计算当前可视区域的起始索引(startIndex)和结束索引(endIndex):
const startIndex = Math.floor(scrollTop / itemHeight);
const endIndex = Math.min(startIndex + visibleCount, list.length);
3. 动态渲染子元素
通过切片(slice)截取需要渲染的数据,并通过绝对定位(position: absolute)和transform调整子项位置:

const visibleData = list.slice(startIndex, endIndex);
const offsetY = startIndex * itemHeight;
4. 监听滚动事件
监听容器的scroll事件,实时更新startIndex和endIndex,触发重新渲染。
代码实现示例
固定高度虚拟列表
<template>
<div class="virtual-scroll" @scroll="handleScroll" ref="container">
<div class="scroll-content" :style="{ height: totalHeight + 'px' }">
<div
v-for="item in visibleData"
:key="item.id"
class="item"
:style="{ height: itemHeight + 'px', transform: `translateY(${item.offset}px)` }"
>
{{ item.content }}
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
list: [], // 原始数据
itemHeight: 50, // 每项高度
startIndex: 0,
endIndex: 0,
visibleCount: 0, // 可视区域可展示的项数
};
},
computed: {
totalHeight() {
return this.list.length * this.itemHeight;
},
visibleData() {
return this.list.slice(this.startIndex, this.endIndex).map((item, index) => ({
...item,
offset: (this.startIndex + index) * this.itemHeight,
}));
},
},
mounted() {
this.visibleCount = Math.ceil(this.$refs.container.clientHeight / this.itemHeight);
this.endIndex = this.startIndex + this.visibleCount;
// 模拟数据
this.list = Array.from({ length: 1000 }, (_, i) => ({ id: i, content: `Item ${i}` }));
},
methods: {
handleScroll() {
const scrollTop = this.$refs.container.scrollTop;
this.startIndex = Math.floor(scrollTop / this.itemHeight);
this.endIndex = this.startIndex + this.visibleCount;
},
},
};
</script>
<style>
.virtual-scroll {
height: 400px;
overflow-y: auto;
border: 1px solid #eee;
}
.scroll-content {
position: relative;
}
.item {
position: absolute;
width: 100%;
box-sizing: border-box;
border-bottom: 1px solid #ccc;
}
</style>
动态高度虚拟列表
若子项高度不固定,需先测量高度并缓存,后续滚动时通过累加偏移量计算位置。可使用ResizeObserver或滚动锚定技术实现。
性能优化建议
- 使用
requestAnimationFrame:节流滚动事件,避免频繁计算。 - 复用DOM节点:通过
v-for的:key标识复用已渲染元素。 - 预渲染:提前渲染可视区域外的部分内容,减少滚动时的空白闪烁。
现有库推荐
- vue-virtual-scroller:支持动态高度和横向滚动。
- vxe-table:表格组件内置虚拟滚动。
- react-window(React生态,原理可参考)。
通过上述方法或直接使用成熟库,可高效实现Vue虚拟滚动。






