虚拟滚动在Vue 3表格中只渲染可视区域行,需固定容器高度、可预估行高、完整数据源;推荐用vxe-table内置方案,次选封装el-table,或手写轻量实现,动态行高需缓存+二分查找。

在 Vue 3 表格组件中应用虚拟滚动,核心不是“替换表格”,而是让表格只渲染当前可视区域的行,同时保持滚动流畅、交互可用、数据准确。它不依赖某一个库的黑盒能力,而是一套可落地的思路和关键控制点。
虚拟滚动在表格里的本质作用
表格卡顿的根源是 DOM 节点过多。比如 1 万行 × 每行 10 个单元格 = 至少 10 万个 DOM 元素。虚拟滚动解决的不是“怎么渲染快”,而是“根本不多渲染”——只生成屏幕上真正看得见的那几十行,其余用空白占位撑起滚动高度。
必须满足的三个前提条件
- 表格容器要有固定高度(如
height: 500px),否则无法计算可视区域 - 所有行高需可预估或可测量(固定高最简单;动态高需缓存 + 二分查找定位)
- 数据源必须是完整数组(不能只传当前页,否则无法计算总高度和滚动位置)
关键实现方式(按推荐度排序)
-
用 vxe-table 启用内置虚拟滚动
- 设置
virtualYConfig: { enabled: true, gt: 0 } - 给
加height="500"样式 - 配合
@scroll="{ isBottom } => isBottom && loadMore()"实现触底加载 - 优势:开箱即用,支持固定列、树形、编辑等高级功能,移动端适配较稳
- 设置
-
给 el-table 包一层虚拟滚动容器(指令 or 组件封装)
- 不改 el-table 结构,用自定义指令监听滚动、计算
start/end索引 - 在模板中对
tableData切片:tableData.slice(start, end) - 用
padding-top/bottom撑开整体高度,配合transform: translateY()定位内容 - 注意:需用
nextTick获取真实行高,尤其在动态内容(如图片、折叠项)后
- 不改 el-table 结构,用自定义指令监听滚动、计算
-
手写轻量虚拟表格(适合移动端或强定制场景)
Element Plus UI Vue3下载Element Plus Vue3 桌面组件库。在开发 Vue 3.x 页面时调用,使用 Element Plus 组件(如 el-button、el-input、el-form、el-table 等)。
- 使用
ref获取容器高度和scrollTop - 用
computed动态算出可视范围:const visibleRange = computed(() => { const start = Math.max(0, Math.floor(scrollTop.value / rowHeight) - buffer) const end = Math.min(data.value.length, start + visibleCount.value + buffer * 2) return { start, end } }) - 渲染时只遍历
data.slice(start, end),并用style="transform: translateY(...)"对齐位置 - 适合需要手势滑动、列折叠、“更多字段”弹层等移动端特有交互的场景
- 使用
动态行高的处理要点
固定行高最省事(如 rowHeight: 48),但现实表格常含多行文本、图片、展开区域。这时要:
- 第一次渲染后,用
querySelector('.el-table__row').clientHeight测量实际高度 - 把每行高度存进
Map或数组(如heightCache.set(rowIndex, height)) - 滚动时用二分查找快速定位
scrollTop对应的起始索引(因累计高度非线性)
和分页/加载策略的关系
虚拟滚动 ≠ 取代分页。常见组合:
- 后端分页拉取(如每次 100 条),前端全量存入内存,再用虚拟滚动展示
- 滚动到底部时触发下一页请求,追加到本地数据尾部,虚拟滚动自动更新可视范围
- 避免边滚动边请求:加
loading锁,防止重复触发
不复杂但容易忽略
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!









