直接减少 dom 节点数量是最有效的性能提升方式,包括精简表格层级、禁用冗余容器、避免嵌套、按需渲染、合并单元格、用原生 table 替代封装组件、冻结数据、优化固定列及禁用 hover 动画。
直接减少 dom 节点数量是最有效的性能提升方式。大规模报表卡顿、内存飙升、滚动不流畅,根源往往不是数据量本身,而是浏览器要同时处理几万个 <tr>、<code><td> 甚至嵌套组件——这远超浏览器高效渲染的承受阈值。
<h3>精简表格 DOM 层级,避免冗余包裹</h3>
<p>Element UI、Ant Design 等主流组件默认生成多层嵌套结构(如 <code><div class="el-table__body-wrapper"><table><tbody><tr>…</tr></tbody></table></div>),其中部分 wrapper 容器对渲染无实质作用,却增加样式计算和重排开销。
- 禁用非必要装饰容器:如 Element UI 中通过
:show-header="false"或移除el-table__header-wrapper(若无需表头)可减少约 15% 的 DOM 节点 - 避免在
<td> 内嵌套多层 <code><div> 包裹文本或图标;优先用纯文本 + CSS 控制样式,例如用 <code>white-space: nowrap替代额外的<span></span>包裹 - 慎用“单元格插槽”渲染重型组件(如
<el-select></el-select>、<el-date-picker></el-date-picker>)——它们每个实例都带来独立 Vue 实例、事件监听器和样式作用域,DOM 节点数呈倍数增长 - 对非关键列(如“操作”“备注”“日志摘要”)启用懒加载:初始仅渲染前 5 列,其余列在用户横向滚动到可视区域后动态插入
- 使用
v-if替代v-show控制条件单元格:当某类状态(如“审核中”)下才需展示审批按钮时,用v-if="row.status === 'pending'"可彻底跳过该 DOM 创建 - 对重复值做合并渲染:相同 ID 或分组字段连续出现时,用
rowspan合并单元格,减少<td> 数量(例如 100 行同属一个部门,可合并为 1 个 <code><td rowspan="100">) <h3>用原生 table 结构替代框架封装表</h3> <p>当业务逻辑简单、交互需求有限(如仅展示+导出),直接使用原生 <code><table> 配合 <code>document.createElement或innerHTML批量拼接,性能远超任何 Vue/React 封装组件。- 实测:10,000 行 × 8 列数据,原生 DOM 拼接耗时约 40–60ms;Element UI 全量渲染需 2.3s 以上
- 关键技巧:预先计算行高(如固定 44px),用
scrollHeight+scrollTop动态截取数据切片,再批量写入tbody.innerHTML - 注意规避响应式陷阱:不将原始数据设为
reactive,改用普通对象 +Object.freeze防止 Vue 建立依赖追踪
冻结关键列,减少横向滚动重绘
横向滚动卡顿常因固定列与主表不同步导致反复重排。Element UI 等采用 6 个
<table> 并列实现固定列,但每个 table 都渲染全部列,造成大量不可见 DOM 浪费。 <ul> <li>只让 fixed 列 table 渲染真正固定的列(如 ID、姓名),主 table 渲染其余列,通过 JS 同步 <code>rowHeight和滚动偏移 - 用
position: sticky替代多 table 方案(兼容性要求 Chrome 56+/Safari 15.4+):单个<table> 内,给关键列 <code><th>/</th> <td> 加 <code>sticky样式,大幅简化 DOM 结构 - 禁用
hover类样式动画:如.el-table__row:hover触发重绘,改为仅用background-color纯色切换,避免 GPU 合成开销
按需渲染单元格内容,而非整行整列
传统全量渲染会为每行每列都生成 DOM,哪怕该单元格只是显示一个静态字符串。优化方向是只在真正需要时才创建节点。










