虚拟滚动需结构设计+css定位+js控制,核心是只渲染可视行;必须统一固定行高、三层dom模拟滚动、节流监听并批量更新tbody内容。

直接用 <table> 标签本身无法实现虚拟滚动——它只是语义容器,不带滚动逻辑。真正起作用的是结构设计 + CSS 定位 + JS 控制渲染范围。核心不是“表格怎么滚”,而是“怎么让浏览器只画当前看得见的几行”。
<h3>必须预设固定行高</h3>
<p>虚拟滚动依赖精确计算:滚动多少像素对应第几行。如果每行高度不一致,就得反复调用 <code>getBoundingClientRect() 测量,性能直接崩盘。所以第一件事是统一行高:
- 给
<tr> 或 <code><td> 设固定 <code>height: 42px(或类似值),并加box-sizing: border-box - 禁用
white-space: normal导致文字换行撑高;改用white-space: nowrap; overflow: hidden; text-overflow: ellipsis - 图片、图标等内联元素也需约束尺寸,避免意外拉高
- 中间层:占位容器,
position: relative,高度 = 总行数 × 行高(例如height: 100000px) - 最里层:只放当前可视区域的
<tr>,每个用 <code>position: absolute+top精确定位(如第 127 行就设top: 127 × 42)滚动监听要节流且只更新必要内容
原生
scroll事件每秒触发几十次,直接响应会卡死。正确做法是:- 用
requestIdleCallback或setTimeout(..., 0)延迟处理,让出主线程 - 每次只算两个值:起始索引
Math.floor(scrollTop / rowHeight)和可视行数Math.ceil(containerHeight / rowHeight) + 4 - 用
slice()截取数据片段,清空旧 DOM 后批量插入新<tr>,别用 <code>innerHTML +=别在 table 内部强行套 virtual-scroll 库
很多 UI 库的虚拟滚动组件默认基于
<div> 渲染,若硬套进 <code><table> 会破坏 HTML 表格语义和可访问性。更稳妥的方式是: <ul><li>保留 <code><table> 外壳(含 <code><thead> 固定表头),但把 <code><tbody> 替换为自定义容器 <li>表头用 <code>position: sticky; top: 0实现固定,兼容现代浏览器 - 若需 IE11 支持,改用
position: absolute+ 监听scroll手动同步表头位置
- 用
用三层 DOM 结构模拟滚动空间
不能把所有 <tr> 都塞进 <code><tbody>。要拆成三部分:
<ul>
<li>最外层:滚动容器,设 <code>height: 500px; overflow-y: auto











