批量插入DOM节点的高效方法,页面性能提升就这么简单

做网页开发时,经常要往页面里塞一堆内容,比如加载一长串商品、动态生成表格数据。如果一个一个地插DOM节点,页面卡得像老电脑开Photoshop,用户点一下等三秒,体验直接崩了。

为什么不能逐个插入?

每次用 appendChildinnerHTML 添加单个元素,浏览器都会触发一次重排(reflow)和重绘(repaint)。插100个节点就可能跑100次渲染流程,资源白白浪费。就像你搬家非要一趟搬一颗螺丝钉,累死还慢。

用 DocumentFragment 批量操作

最推荐的方式是使用 DocumentFragment。它是个虚拟的DOM容器,不会直接显示在页面上。你可以先把所有节点丢进去,拼装好后再一次性插入真实DOM。

const fragment = document.createDocumentFragment();
const items = ['苹果', '香蕉', '橙子', '葡萄'];

items.forEach(item => {
  const li = document.createElement('li');
  li.textContent = item;
  fragment.appendChild(li);
});

document.querySelector('ul').appendChild(fragment);

这段代码只触发一次页面重绘,速度明显快很多。适合列表、选项、日志这类需要动态填充的场景。

innerHTML 拼接字符串也行,但要小心

如果你不涉及事件绑定,纯展示内容,直接拼HTML字符串再赋值给 innerHTML 也是可行的。

const items = ['苹果', '香蕉', '橙子'];
const htmlString = items.map(name => 
  `<li>${name}</li>`
).join('');

document.querySelector('ul').innerHTML = htmlString;

这种方法写起来简单,执行也快,但要注意XSS风险,别把用户输入直接拼进去。

现代框架早帮你搞定了

Vue、React 这些框架内部已经做了批量更新优化。比如React的 useState 多次调用会被合并,Virtual DOM 也会在提交前攒一波操作再刷到页面。但如果你在这些框架里直接操作原生DOM,一样会掉坑里。

所以就算用了框架,了解底层机制还是有必要的。哪天要写个高性能组件,或者调试卡顿问题,这些知识就派上用场了。

实际应用场景

比如你做个后台管理系统,要渲染上千条订单记录。用循环一个个插,页面卡到怀疑人生。换成 DocumentFragment 或字符串拼接,唰一下就出来了,老板路过看你屏幕都以为加了SSD。

再比如聊天页面,一次性来几十条消息,如果每条都单独插入,不仅卡,还会导致滚动位置乱跳。批量处理就能稳稳地把消息堆上去,用户体验顺滑得多。