Vue 3 多列网格虚拟滚动需将二维数据扁平化为一维数组,按行列范围动态渲染可见单元格,支持固定或动态行列尺寸,并推荐使用 vue-virtual-scroller 的 Grid 模式提升可靠性。

Vue 3 中实现多列网格布局的虚拟滚动,核心是把“单列列表”的虚拟化逻辑扩展为二维坐标系下的可见区域计算:既要算出垂直方向上哪些行在视口内,也要算出水平方向上哪些列在可视范围内。它不是简单套用 v-for + CSS Grid 就能解决的,必须手动控制渲染范围、占位高度/宽度,并动态定位每个单元格。
关键思路:把网格当“扁平化二维数组”来管理
假设你有 1000 行 × 4 列的数据(共 4000 项),不要直接用 grid-template-columns: repeat(4, 1fr) 渲染全部;而是把它看作一个长度为 4000 的一维数组,每项带 rowIndex 和 colIndex。这样就能复用单列虚拟滚动的大部分逻辑,只需在计算可见索引时引入列维度:
- 先根据容器高度、行高(或动态行高缓存)、滚动位置
scrollTop算出可见的起始行startRow和结束行endRow - 再根据容器宽度、列宽(或列宽数组)、水平滚动位置
scrollLeft(需启用overflow-x: auto)算出可见列范围startCol~endCol - 最终可见项 = 所有满足
startRow ≤ rowIndex ≤ endRow且startCol ≤ colIndex ≤ endCol的单元格
固定行列尺寸:最简可行方案
若每行高固定(如 60px)、每列宽固定(如 200px),实现最轻量:
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
- 用一个
<div class="grid-container">作为滚动容器,设height、overflow-y: auto,并加display: grid和grid-template-columns: repeat(4, 200px) - 顶部占位元素高度 =
startRow × 60,撑开滚动条比例 - 只渲染
(endRow - startRow + 1) × 4个单元格(注意:列数固定为 4,不随水平滚动变化) - 每个单元格用
position: absolute+top/left精确定位:top = rowIndex × 60,left = colIndex × 200
支持水平滚动的进阶处理
如果网格列数远超容器宽度(比如 20 列),需要同时支持横向和纵向滚动:
立即学习“前端免费学习笔记(深入)”;
- 容器设
overflow: auto,监听@scroll获取scrollTop和scrollLeft - 预计算每列宽度并存入数组(如
colWidths = [180, 220, 160, ...]),用前缀和数组colOffsets加速列定位(类似动态高度中的累计高度) - 用二分查找快速定位
scrollLeft对应的startCol(查colOffsets数组) - 渲染区域变为矩形块:
[startRow, endRow] × [startCol, endCol],总项数可控(例如最多渲染 5 行 × 6 列 = 30 个 DOM)
真实项目推荐:用 vue-virtual-scroller 的 Grid 模式
手写二维虚拟滚动调试成本高。更稳的方式是使用已验证的库:
-
vue-virtual-scroller 提供
<virtual-scroller-grid>组件,原生支持行列配置、slot 分发、动态尺寸回调 - 安装:
npm install vue-virtual-scroller,注册后直接用:<virtual-scroller-grid :items="gridData" :item-size="[60, 200]" :columns="4"><br> <template #default="{ item }"><br> <div>{{ item.content }}</div><br> </template><br></virtual-scroller-grid> - 它内部自动处理行列映射、占位、节流、缓存,比自己实现更可靠,尤其适合中后台复杂表格场景

















