createDocumentFragment 是浏览器原生 API,返回一个不挂载 DOM 的轻量级容器节点,用于暂存多个子节点后一次性插入,避免频繁重排重绘;小量节点(≤3)优化不明显,但列表渲染等场景可显著提升性能。

createDocumentFragment 是什么,为什么不用直接 append
createDocumentFragment 是浏览器原生 API,返回一个轻量级的、不挂载到 DOM 树中的容器节点。它常被用来「暂存」多个节点,在一次性插入时避免频繁触发重排(reflow)和重绘(paint)。直接用 appendChild 循环插入 10 个 div,浏览器可能重排 10 次;而先塞进 DocumentFragment 再插入一次,只重排 1 次。
注意:它不是“必须用”的优化手段,小量节点(比如 ≤3 个)几乎无感知;但遇到列表渲染、动态表格生成、富文本解析等场景,就容易成为性能瓶颈点。
怎么创建并批量添加子节点
核心流程就是三步:创建 → 填充 → 插入。关键在于所有 append / appendChild 都作用在 fragment 上,最后只调用一次真实父节点的插入方法。
const frag = document.createDocumentFragment();
for (let i = 0; i < 5; i++) {
const item = document.createElement('li');
item.textContent = `Item ${i + 1}`;
frag.appendChild(item); // 注意:这里 append 的是 fragment,不是 body 或 ul
}
document.getElementById('myList').appendChild(frag); // 一次插入完成
-
frag本身没有innerHTML属性,不能直接赋值字符串,只能用createElement+appendChild或append - 支持
append()(可传多个参数)、appendChild()(只接受单个 Node),但不支持insertAdjacentHTML - 插入后,
frag自动清空——再次使用需重新createDocumentFragment()
和 innerHTML 拼接字符串比,哪个更快
纯 HTML 字符串拼接 + innerHTML 通常更快(尤其节点结构简单时),但有明显短板:innerHTML 会销毁已有绑定的事件监听器、丢失表单状态(如 input.value)、且存在 XSS 风险(若内容未转义)。
立即学习“前端免费学习笔记(深入)”;
DocumentFragment 则保持节点对象完整性,适合需要保留 JS 引用、动态控制或后续交互的场景。
- 要插纯静态列表?
innerHTML更快也更简短 - 要给每个
li绑定不同data-id并预留 click 处理?用DocumentFragment更可控 - 如果内容来自用户输入,
innerHTML += unsafeStr是危险操作;而textContent+DocumentFragment天然防 XSS
常见错误:fragment 插入后子节点消失或报错
最典型的误操作是:把 fragment 当成普通容器反复使用,或误以为它能跨多次插入生效。
- 错误:插入一次后,再对同一
frag调用appendChild(frag)—— 第二次会静默失败,因为 fragment 已无子节点(DOM 规范规定 fragment 只能被插入一次,移动时自动清空) - 错误:用
frag.querySelector——DocumentFragment不支持querySelector,得用getElementById或先 append 到真实 DOM 再查 - 错误:在 fragment 上监听事件(如
frag.addEventListener)—— 它不触发冒泡,也不响应事件,事件必须挂在真实父节点或子元素上
真正容易被忽略的是:fragment 的生命周期极短,它只为“过渡”而生,写完插入就得丢弃重造。


















