documentfragment 是轻量级离线 dom 容器,不触发重排重绘;因其操作在内存中进行,仅一次性插入真实 dom 时执行一次布局绘制,从而将多次 dom 操作合并为单次更新,显著提升批量渲染性能。

DocumentFragment 是什么,为什么能减少 DOM 操作
DocumentFragment 是一个轻量级的 DOM 容器,它不直接属于主文档树,插入或修改它不会触发页面重排(reflow)或重绘(repaint)。当你需要批量添加多个节点时,先把这些节点 append 到 DocumentFragment,再一次性插入到真实 DOM,就能把多次 DOM 操作合并为一次。
常见错误现象是:循环中反复调用 element.appendChild(child),每次都会让浏览器尝试更新布局,尤其在节点多、结构深时,性能明显下降。
使用场景包括:
- 动态生成列表项(比如从数组渲染 li)
- 构建复杂表单或卡片结构
- 在事件处理中批量更新界面(如拖拽后重排)
怎么创建和填充 DocumentFragment
创建很简单:const frag = document.createDocumentFragment()。之后所有 appendChild、append、insertBefore 都可以照常调用,只是目标是 frag 而不是真实元素。
注意几个关键点:
- DocumentFragment 不能被直接查询(querySelector 不起作用),它只是临时容器
- 它没有 innerHTML 属性,必须用 DOM 方法逐个添加节点
- 插入后,frag 会清空自身内容(节点被移走),再次使用需重新创建
const frag = document.createDocumentFragment();
const items = ['苹果', '香蕉', '橙子'];
items.forEach(text => {
const li = document.createElement('li');
li.textContent = text;
frag.appendChild(li); // 这里不触发 DOM 更新
});
document.getElementById('list').appendChild(frag); // 只这里触发一次
和 innerHTML + createElement 对比有什么区别
innerHTML 写法快、简洁,但有 XSS 风险,且无法复用已有节点引用;createElement + DocumentFragment 更安全、可控,适合需要绑定事件或保留 JS 引用的场景。
参数差异和性能影响:
- innerHTML 字符串解析开销小,但每次都要重建整个子树,旧节点引用失效
- DocumentFragment 允许你复用已创建的节点(比如预先绑定好 click 事件的 button),也支持条件插入(if 判断后才 appendChild)
- 在 Chrome/Firefox 中,100+ 节点批量插入时,DocumentFragment 通常比连续 appendChild 快 2–5 倍;但比 innerHTML 略慢(约 10%~20%),优势在于控制力而非绝对速度
容易忽略的兼容性和边界情况
DocumentFragment 在 IE9+ 和所有现代浏览器中完全可用,但要注意:
- 它不支持
dataset或classList(因为它不是 Element) - 不能用
frag.style.color = 'red'—— 它没有样式接口 - 如果你误把
frag当成普通元素传给第三方库(比如某些 UI 组件的render方法),可能报错“not a valid node”
最常被忽略的一点是:很多人以为只要用了 DocumentFragment 就一定更快,其实不然。如果只插入 1–2 个节点,或者操作本身就很轻量,反而可能因额外创建对象带来微小开销。真正收益出现在「批量」和「高频」场景下,比如虚拟滚动中每帧插入 20+ 行,或者表格导出时生成数百行 tr。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











