DocumentFragment 是轻量级文档片段容器,不直接属于 DOM 树,操作它不会触发重排或重绘;仅当一次性 appendChild 到真实 DOM 时才引发一次布局计算,显著提升批量插入性能。

DocumentFragment 是什么,为什么能减少重排
它是个轻量级的文档片段容器,不直接属于 DOM 树,对它的操作不会触发页面重排(reflow)或重绘(repaint)。只有把它一次性 appendChild 到真实 DOM 节点时,才引发一次布局计算。这比逐个 appendChild 多个节点高效得多——后者每插入一个就可能触发一次重排,尤其在父容器已挂载、样式复杂时更明显。
怎么创建并填充 DocumentFragment
用 document.createDocumentFragment() 实例化后,就可以像操作普通父节点一样往里塞子节点:
const frag = document.createDocumentFragment();
for (let i = 0; i < 100; i++) {
const li = document.createElement('li');
li.textContent = `Item ${i}`;
frag.appendChild(li); // 不触发重排
}
// 只有这一句会触发一次重排
document.getElementById('list').appendChild(frag);
- 不能用
innerHTML直接赋值给frag(它没该属性),必须用appendChild/append等方法逐个加节点 - 可以混用
DocumentFragment和真实 DOM 节点:比如先建好一组div,再把它们一起appendChild进 frag - 注意:frag 插入后自动清空,不能再重复使用
和 innerHTML 拼接字符串比,有什么区别
两者都是一次性写入,但行为不同:
-
innerHTML字符串拼接快,但需手动转义防止 XSS,且无法复用已有节点引用(只能生成新节点) -
DocumentFragment支持复用已有节点(frag.appendChild(existingNode)),也天然规避 XSS(不解析 HTML 字符串) - 性能上,小批量节点(50)且含事件绑定或复杂结构时,frag 更可控——因为你能精确控制每个节点的创建和属性设置过程
容易忽略的边界情况
实际用的时候,这几个点常被跳过导致效果打折:
立即学习“前端免费学习笔记(深入)”;
- 别在循环里反复调用
document.createDocumentFragment()——应该只创建一次,然后持续往里 append - 如果目标父节点是
table,不能直接把tr塞进 frag 后 append 到table,得先 append 到tbody或thead;否则浏览器会静默修正,可能破坏 frag 的预期行为 - frag 不支持
querySelector等查找方法(它不是完整文档),调试时想检查内容,得先临时 append 到 body 看一眼,再移走
真正起效的前提,是你确认目标操作确实引发了重排——比如父元素已渲染、有高度/宽度/浮动等依赖布局的样式。如果父节点还处于内存中未挂载,那无论怎么插都不会重排,用不用 frag 都一样。



















