documentfragment 是离线轻量容器,不触发重排;将多次 dom 操作合并为一次插入时的布局计算,从而减少重排。它不支持 queryselector 和直接事件绑定,但比 innerhtml 更安全,且在 ie9+ 原生支持。

DocumentFragment 是什么,为什么它能减少重排
DocumentFragment 不是真实 DOM 树的一部分,它是个离线的轻量容器,往里面 appendChild 任何节点都不会触发浏览器渲染流程。很多人误以为“快”是因为 JS 执行快,其实关键在于:它把原本 100 次可能触发重排的操作,压缩成 1 次真实插入时的布局计算。
重排(reflow)发生在元素几何属性变化时,比如宽高、位置、字体大小等;而 DocumentFragment 完全绕过这个阶段——直到你调用 container.appendChild(fragment) 那一刻,浏览器才开始计算整个 fragment 子树的布局。
- fragment 插入后自动清空,不可复用;需多批操作就每次新建一个
- 它不支持
querySelector或事件监听器直接绑定(因为没挂载),但可配合事件委托使用 - 比字符串拼接
innerHTML更安全:不会丢失已有事件监听器,也无 XSS 风险(前提是不用innerHTML注入未过滤内容)
怎么写才不踩坑:常见错误写法对比
下面这些写法看着差不多,但性能和行为差异极大:
❌ 错误:在循环里反复操作真实 DOM
const container = document.getElementById('list');
for (let i = 0; i
<p>❌ 危险:用 <code>innerHTML +=</code> 拼接</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill5493" title="html-to-pptx"><img
src="https://img.php.cn/upload/skill/000/000/081/179051045119472.jpg" alt="html-to-pptx" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill5493" title="html-to-pptx" class="overflowclass">html-to-pptx</a>
<p class="overflowclass">将多页 HTML 演示文稿转换为美化的 PPTX 文件,便于分享和分发。</p>
</div>
<a rel="nofollow" href="/xiazai/skill5493" title="html-to-pptx" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
<pre class="brush:php;toolbar:false;">el.innerHTML += '
✅ 正确:用 DocumentFragment 批量组装
const fragment = document.createDocumentFragment(); for (let i = 0; i <h3>什么时候该换别的方案?DocumentFragment 的边界</h3> <p>DocumentFragment 并非万能。以下场景它帮不上忙,甚至会适得其反:</p>
- 只插入 1–2 个节点:开销反而略高于直插,没必要封装
- 需要保留对每个新节点的引用并后续单独操作(比如加动画 class、绑定不同事件):fragment 插入后节点就脱离 fragment,但引用仍有效;不过若逻辑复杂,不如先存数组再批量处理
- 更新已有 DOM 节点的样式或文本内容(非新增):这时应避免循环中混用读写,优先用
el.className = 'xxx'或el.style.cssText = '...'合并写入 - 渲染上万行数据:即使用了 fragment,一次性插入仍会让主线程卡顿 >100ms。必须配合
requestIdleCallback或requestAnimationFrame分帧,每帧处理 20 个左右
兼容性和 fallback 注意点
DocumentFragment 在所有现代浏览器和 IE9+ 都原生支持,无需 polyfill。但如果你的项目仍需支持 IE8 及更早版本,document.createDocumentFragment() 会返回 undefined,此时可 fallback 到临时容器技巧:
const frag = document.createDocumentFragment ?
document.createDocumentFragment() :
document.createElement('div');
注意:IE8 下用 div 替代时,记得最后用 frag.innerHTML 清空内容,否则可能残留;且不能依赖 frag.childNodes.length 判断是否为空——IE8 中它始终为 0。
真正容易被忽略的是:DOM 操作的延迟感知不在 JS 引擎,而在浏览器渲染流水线。哪怕你优化到毫秒级,只要触发了强制同步布局(比如循环里读 offsetHeight 再写 style),整套优化就归零。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










