核心是强制启用table-layout:fixed、用管列宽、分批插入DOM节点;缺一不可,否则必然卡死。因auto模式逐行扫描内容计算列宽会阻塞主线程,fixed模式仅读第一行或即可确定列宽,配合DocumentFragment每500–1000行插入并让出主线程,才能保障性能。

直接重构千行以上报表表格,核心就三件事:强制启用 table-layout: fixed、用 <colgroup></colgroup> 管列宽、分批插入 DOM 节点——缺一不可,否则卡顿是必然的,不是“可能慢”,而是“一定卡死”。
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
为什么必须显式写 table-layout: fixed 并配 width
浏览器默认用 auto 模式算列宽,会逐行扫描所有 <td> 内容(含长文本、未限制宽的图片、内联样式),500 行 × 15 列就能卡主线程 150ms+。设成 <code>fixed 后,它只看第一行或 <col>,列宽瞬间确定。
<table> 必须带明确宽度,例如 <code>style="width: 100%; table-layout: fixed;",靠父容器继承或 reset.css 不生效- 列宽声明只能落在
<col>上(写在<th> 或 <code><td> 的 <code>width属性会被忽略) - 禁用
min-width/max-width:它们在fixed模式下常被跳过,导致列意外坍缩或撑开 - 响应式改列宽,用
@media控制<col>的width,别在单元格里写min-width - 每列对应一个
<col>,例如:<col width="120">、<col width="25%">、<col width="80"> - 横向合并表头(如
<th colspan="2">)时,对应 <code><colgroup span="2"></colgroup>,不能混用span和width - 为分组表头提供语义:主标题加
scope="colgroup",子列标题各加scope="col" - 避免在
<col>上写style="width: auto"——auto在fixed下行为不可控,优先用百分比或像素值 - 必须用
DocumentFragment批量构建,每 500–1000 行插入一次fragment - 每次插入后加
await new Promise(r => setTimeout(r, 0)),让出主线程,保持滚动/输入响应 - 服务端返回 JSON,前端控制节奏;坚决不用
jQuery.html()或原生innerHTML = str - 若需 XSS 防护,用轻量函数如
escapeHtml()处理字段,别引入重型 sanitizer - 真正有效的虚拟滚动,是只渲染视口内 ±1~2 屏的数据行,其余用占位
<tr> 填充高度 <li>必须预设每行高度(或缓存动态高度),否则无法精确计算滚动偏移和占位高度</li> <li>不要自己手写滚动监听 + 重渲染;用成熟方案如 <code>virtuoso(Vanilla/TS)或react-window(React) - 禁用
will-change: transform在滚动容器上——它反而触发额外合成层,增加内存压力
怎么用 <colgroup></colgroup> 真正控制列宽和语义
<colgroup></colgroup> 不是可有可无的装饰标签,它是 fixed 模式下唯一可靠的列宽入口,也是读屏器识别列结构的关键锚点。
为什么不能一次性 innerHTML = hugeString
一次性插入 5000 行字符串,不是 JS 慢,是浏览器在 DOM 构建阶段被压垮:字符串解析 + 节点创建 + 回流计算全堆在一次调用里。哪怕用 document.createElement 单个追加 5000 次,照样卡顿。
立即学习“前端免费学习笔记(深入)”;
虚拟滚动不是加 overflow: auto 就完事
只给容器设 display: block 和 overflow-y: auto,DOM 节点还在那儿,浏览器照常解析布局——对 200 行以上毫无意义。
最容易被忽略的是:就算你写了 <thead>,如果它没放在 <code><table> 的第二子元素位置(<code><caption></caption> 和 <colgroup></colgroup> 之后),sticky 就会失效、打印丢表头、JS 获取 tbody 为空——这不是“看起来差不多”,是结构性错误。


















