1. 安装与基础配置
首先安装 vue-virtual-scroller 依赖:
bash
npm install vue-virtual-scroller
在入口文件(如 main.js)中注册插件:
javascript
import Vue from 'vue'
import VueVirtualScroller from 'vue-virtual-scroller'
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
Vue.use(VueVirtualScroller)
插件注册后,全局组件 RecycleScroller、DynamicScroller 和 DynamicScrollerItem 即可直接使用。
2. RecycleScroller 基础用法
RecycleScroller 是核心组件,适用于固定高度列表项的场景。它只渲染可视区域内的节点,并在滚动过程中复用 DOM 元素,从而显著降低长列表的内存占用。
vue
<template>
<RecycleScroller
class="scroller"
:items="list"
:item-size="50"
key-field="id"
v-slot="{ item }"
>
<div class="row">
{{ item.name }}
</div>
</RecycleScroller>
</template>
<script>
export default {
data() {
return {
list: Array.from({ length: 10000 }, (_, i) => ({
id: i,
name: `Item ${i}`
}))
}
}
}
</script>
<style scoped>
.scroller {
height: 400px;
overflow-y: auto;
}
.row {
height: 50px;
line-height: 50px;
border-bottom: 1px solid #eee;
}
</style>
关键参数说明:
- items:数据源数组。
- item-size:每项固定高度(像素),必须准确设置。
- key-field:唯一标识字段,用于节点复用。
- v-slot:作用域插槽,接收当前渲染项。
3. DynamicScroller 处理不定高度
当列表项高度不固定时,使用 DynamicScroller 配合 DynamicScrollerItem 实现动态测量。组件会在渲染过程中自动获取每项实际高度并缓存。
vue
<template>
<DynamicScroller
class="scroller"
:items="list"
:min-item-size="50"
key-field="id"
v-slot="{ item, index, active }"
>
<DynamicScrollerItem
:item="item"
:active="active"
:data-index="index"
>
<div class="dynamic-row">
<p>{{ item.title }}</p>
<p v-if="item.desc">{{ item.desc }}</p>
</div>
</DynamicScrollerItem>
</DynamicScroller>
</template>
<script>
export default {
data() {
return {
list: [
{ id: 1, title: '短内容', desc: '' },
{ id: 2, title: '长内容', desc: '这是一段较长的描述文本,用于演示动态高度场景下的渲染效果。' },
{ id: 3, title: '短内容', desc: '' }
]
}
}
}
</script>
使用 DynamicScroller 时需要注意:
- min-item-size:预估最小高度,用于初始渲染占位。
- active:表示该项是否处于可视区域,可用于延迟加载图片等操作。
- 每项内容变化后,组件会自动重新测量高度。
4. 大数据量下的性能优化
当列表数据量达到数万甚至十万级时,除了虚拟滚动本身,还需要配合以下手段进一步优化性能:
- 按需渲染子组件:在插槽内避免直接渲染复杂子组件,尽量使用轻量模板。
- 配合 v-memo:在 Vue 3 中可对插槽内容使用 v-memo 减少不必要的更新。
- 延迟加载图片:利用 active 状态,仅在项进入可视区域时加载图片资源。
- 避免响应式深度监听:大数据列表建议使用普通数组,避免对每项做深层响应式代理。
vue
<template>
<RecycleScroller
:items="list"
:item-size="80"
key-field="id"
v-slot="{ item, active }"
>
<div class="card">
<img
v-if="active"
:src="item.cover"
alt="cover"
/>
<div class="placeholder" v-else></div>
<p>{{ item.title }}</p>
</div>
</RecycleScroller>
</template>
5. 常见问题与注意事项
在实际项目中使用 vue-virtual-scroller 时,有几个容易踩坑的地方需要特别留意:
- 容器高度必须明确:虚拟滚动依赖容器滚动,父容器需要设置固定高度或可计算高度,否则无法正确计算可视区域。
- item-size 必须准确:RecycleScroller 的 item-size 与实际渲染高度不一致时,会出现滚动跳动或空白区域。
- key-field 必须唯一:重复的 key 会导致节点复用错乱,出现内容串位。
- 列表项避免使用 margin 合并:相邻项的 margin 可能发生折叠,导致高度计算异常,建议使用 padding 或 border 代替。
- 不要在插槽内使用 v-if 切换根元素:根节点类型变化会导致复用节点异常,应保持根元素稳定。
6. 总结
vue-virtual-scroller 通过节点复用和可视区域裁剪,能够有效解决前端长列表渲染的性能瓶颈。固定高度场景优先选择 RecycleScroller,内容高度不固定时使用 DynamicScroller,同时配合容器高度设置、唯一 key 和按需渲染等实践,即可在真实项目中稳定落地。