DocumentFragment能绕过重排,因其脱离DOM树、不参与渲染流程,所有操作在内存中完成,仅最终插入时触发一次重排;正确流程为:创建fragment→批量添加节点→单次append到真实DOM。

用 DocumentFragment 在内存中预构建 DOM 树,本质是把“多次修改真实 DOM”变成“一次插入完整结构”,从而让浏览器只做一次重排。它不渲染、不计算样式、不触发布局,所有操作都在内存里安静完成。
DocumentFragment 为什么能绕过重排
它不是真实 DOM 树的一部分,没有父节点、不在渲染树中,浏览器压根不会为它执行样式计算或布局。你往里面加 100 个 div,不会触发任何重排;只有最后 append 到真实容器时,浏览器才开始算尺寸、排位置、画像素——而且只算这一次。
正确构建流程(三步不能少)
- 调用 document.createDocumentFragment() 创建新片段(每次都要新建,不能复用)
- 用 createElement 或 innerHTML + 克隆/移入 创建节点,再全部 appendChild 到 fragment
- 最后只执行 container.appendChild(fragment) —— 此时 fragment 自动清空,子节点全部迁移到目标容器
常见错误要避开
- 在 fragment 上尝试设置 innerHTML:它不支持,会静默失败
- 循环中直接操作真实 DOM(比如
list.appendChild(li)):每轮都可能强制重排 - 用 innerHTML += htmlString 拼接:每次赋值都会销毁并重建整个子树,性能随节点数平方恶化
- 插入后还想读取 fragment.childNodes:它已空,必须在 append 前处理引用或事件绑定
适合用它的典型场景
- 动态生成表格行(
<tr><td>…</td></tr>批量插入) - 列表项渲染(如聊天消息、商品卡片、日志条目)
- 模态框、下拉菜单等组件的初始化挂载
- 需要保留 input 值、选中状态或已绑定事件的批量更新

















