直接渲染万行表格会卡死大屏,因为浏览器并非为一次性挂载数万个<tr>设计,每增加一个<tr>都会触发DOM构建、样式计算、布局和绘制,滚动时频繁重排,叠加高DPR下内存分配不均与GC延迟,导致首次加载超2秒、滚动卡顿甚至白屏。
因为浏览器不是为一次性挂载数万个 <tr> 设计的。每多一个 <tr>,就触发一次 DOM 构建、样式计算、layout 和 paint;滚动时还要反复重排。大屏高 DPR 下内存分配不均 + GC 延迟,首次加载超 2s、滚动掉帧甚至白屏是常态。
关键不在数据量,而在你让浏览器把所有行都当成“必须立刻渲染”的节点对待。
innerHTML 或循环 appendChild 渲染全部数据单独用 attachShadow 不会提速。真正起效的是:在 Shadow DOM 内部实现虚拟滚动 + DOM 复用池,把实际挂载的 <tr> 控制在可视区域行数 × 2~3 范围内。
rowHeight(如 48),避免动态测量导致计算失效bufferCount 至少设为 Math.ceil(viewportHeight / rowHeight) + 2,上下各多两屏phantomHeight 必须严格等于 totalCount * rowHeight,否则滚动条比例失真createFn 不要绑定事件;recover 必须清空 textContent、innerHTML、dataset 和 style.cssText
模板本身不支持数据绑定,所有插值必须手动操作 DOM 节点。重点不是“怎么填”,而是“在哪填”和“怎么防错”。
立即学习“前端免费学习笔记(深入)”;
connectedCallback 中批量渲染,而非构造函数里——此时元素已挂载,可安全访问 shadowRoot
this.attachShadow({ mode: 'open' }),否则克隆后可能触发非法请求<template> 克隆出的节点默认保留原始 id,多个实例会导致 ID 冲突。推荐模板中用占位符如 id="item-title-{id}",克隆后用正则替换delegatesFocus 必须在 attachShadow 时声明,它是创建 shadow root 的一次性配置,创建后不可读写。
host.shadowRoot.delegatesFocus = true —— 控制台无报错但无效this.attachShadow({ mode: 'open', delegatesFocus: true })
<input>、<button> 或 tabindex="0"),且未被 disabled 或 hidden
focus/blur 事件,需手动桥接:在内部可聚焦元素上监听,再通过 setAttribute('focused', '') 同步状态复杂点在于:既要控制节点数量,又要保证焦点流、ID 唯一性、事件清理和样式隔离——四者缺一不可。漏掉任意一项,都可能在大屏监控或无障碍测试中暴露问题。