vue虚拟列表实现原理
Vue 虚拟列表实现原理
虚拟列表(Virtual List)是一种优化长列表渲染性能的技术,通过仅渲染可视区域内的元素,大幅减少 DOM 节点数量,提升页面性能。
核心原理
-
可视区域计算
通过容器的高度和滚动位置,计算出当前可视区域内需要渲染的列表项范围。
公式:startIndex = Math.floor(scrollTop / itemHeight) endIndex = Math.min(startIndex + visibleCount, totalItems) -
动态渲染
仅渲染startIndex到endIndex之间的列表项,其他区域用空白占位符填充。 -
滚动事件处理
监听容器滚动事件,动态更新startIndex和endIndex,触发重新渲染。
实现步骤
1. 固定高度项实现
适用于列表项高度固定的场景,计算更简单高效。
示例代码:
<template>
<div class="virtual-list" @scroll="handleScroll">
<div class="list-phantom" :style="{ height: totalHeight + 'px' }"></div>
<div class="list-content" :style="{ transform: `translateY(${offset}px)` }">
<div v-for="item in visibleData" :key="item.id" class="list-item">
{{ item.content }}
</div>
</div>
</div>
</template>
<script>
export default {
props: ['listData'],
data() {
return {
startIndex: 0,
endIndex: 0,
itemHeight: 50,
visibleCount: 0,
offset: 0
}
},
computed: {
totalHeight() {
return this.listData.length * this.itemHeight
},
visibleData() {
return this.listData.slice(this.startIndex, this.endIndex)
}
},
mounted() {
this.visibleCount = Math.ceil(this.$el.clientHeight / this.itemHeight)
this.endIndex = this.startIndex + this.visibleCount
},
methods: {
handleScroll() {
const scrollTop = this.$el.scrollTop
this.startIndex = Math.floor(scrollTop / this.itemHeight)
this.endIndex = this.startIndex + this.visibleCount
this.offset = scrollTop - (scrollTop % this.itemHeight)
}
}
}
</script>
2. 动态高度项实现
适用于列表项高度不固定的场景,需要额外维护高度位置信息。
关键点:
- 使用位置缓存记录每个项的位置和高度
- 二分查找确定可视区域范围
- 动态调整后续项的位置
性能优化建议
-
使用 requestAnimationFrame
对滚动事件进行节流,避免频繁触发重排重绘。 -
合理设置缓冲区
可视区域上下额外渲染部分项,防止快速滚动时出现空白。 -
避免复杂计算
将不变的计算结果缓存,减少重复计算开销。
常见问题解决
-
快速滚动闪烁
增加缓冲区大小或使用骨架屏占位。 -
动态内容导致高度变化
监听内容变化,重新计算位置信息。 -
内存占用过高
对不可见项进行销毁,而非仅隐藏。







