你有没有遇到过这种情况:点一下按钮,页面卡一下才反应过来;滚动页面时内容闪烁或者掉帧;表单输入时延迟明显。这些问题很多时候不是网络慢,也不是电脑不行,而是 DOM 操作写得太“暴力”了。
频繁操作是性能杀手
比如你想往页面里加 100 个列表项,有人会这么写:
const list = document.getElementById('myList');
for (let i = 0; i < 100; i++) {
const li = document.createElement('li');
li.textContent = '条目' + i;
list.appendChild(li); // 每次都触发重排重绘
}
这段代码每次 appendChild 都会让浏览器重新计算布局、重绘画面,100 次操作等于 100 次渲染压力,用户自然觉得卡。
用文档片段(DocumentFragment)批量处理
更好的做法是先把所有元素组装好,再一次性插入页面:
const list = document.getElementById('myList');
const fragment = document.createDocumentFragment();
for (let i = 0; i < 100; i++) {
const li = document.createElement('li');
li.textContent = '条目' + i;
fragment.appendChild(li);
}
list.appendChild(fragment); // 只触发一次重排
这样浏览器只在最后插入时做一次渲染更新,页面丝滑多了。
避免重复查询 DOM 元素
有些人习惯反复写 document.getElementById 或 document.querySelector,比如在一个循环里每次都查一遍:
for (let i = 0; i < 10; i++) {
const el = document.querySelector('.item'); // 多余的查找
; el.style.color = 'red';
}
其实查一次存起来就行:
const el = document.querySelector('.item');
for (let i = 0; i < 10; i++) {
el.style.color = 'red';
}
DOM 查询成本不低,能省就省。
样式变动尽量合并
如果你要改多个样式,别一个一个赋值:
el.style.width = '100px';
el.style.height = '100px';
el.style.backgroundColor = 'blue'; // 触发多次重排
可以换成修改 class,或者用 cssText 一次性设置:
el.style.cssText = 'width: 100px; height: 100px; background-color: blue;';
或者提前定义好 class,在 JS 中切换:
el.classList.add('box-active');
善用事件委托
假如你有个很长的列表,每个 item 都要绑定点击事件,别一个个绑:
document.querySelectorAll('.item').forEach(item => {
item.addEventListener('click', () => { /* 处理逻辑 */ });
});
可以只在父容器上监听,利用事件冒泡来判断目标:
document.getElementById('list').addEventListener('click', e => {
if (e.target.classList.contains('item')) {
// 处理点击
}
});
不仅性能好,新增元素也不用重新绑定事件。
离线操作也能提效
有时候你要对某个元素做一连串复杂改动,可以先把它从 DOM 中移除,改完再放回去:
const container = document.getElementById('container');
container.remove(); // 离线
// 做一堆修改
container.innerHTML = '<div>新内容</div>';
container.className = 'updated';
// 改完再插回原位
document.body.appendChild(container);
虽然不常用,但在处理大型结构时能有效减少中间渲染开销。
DOM 操作看着简单,但写法不同,性能差好几倍。平时多注意这些细节,页面自然更跟手,用户也少抱怨卡顿了。