为什么循环生成大量DOM元素时页面会卡顿?有没有更好的优化方法?

素红🍀 阅读 3

我在用JavaScript循环生成2000条带样式的列表项时,页面直接卡住了。尝试把DOM操作移到文档碎片里,渲染完再append,但滑动列表还是会有轻微卡顿。特别是加了CSS过渡效果后更明显:


.list-item {
  transition: all 0.3s;
  padding: 10px;
  border-bottom: 1px solid #eee;
}
.list-item:hover {
  background-color: #f0f0f0;
  transform: scale(1.02);
}

用Chrome性能分析发现主要耗时在Paint阶段。试过把过渡效果改成will-change属性,但滚动时帧率还是掉到30多。有没有什么更直接的优化方式?

我来解答 赞 6 收藏
二维码
手机扫码查看
1 条解答
打工人彤彤
问题出在CSS过渡和大量DOM元素上,Paint和Layout的开销太高了。建议把hover效果改成纯JS处理,减少重绘,再用虚拟列表按需渲染,只保留视口内的DOM。

试试这段代码:

// 虚拟列表核心逻辑
let container = document.getElementById('container');
let itemHeight = 40; // 每个item高度
let visibleCount = Math.ceil(window.innerHeight / itemHeight);

function render(start, end) {
container.innerHTML = ''; // 清空容器
for (let i = start; i < end; i++) {
let item = document.createElement('div');
item.className = 'list-item';
item.style.height = itemHeight + 'px';
item.textContent = 'Item ' + i;
container.appendChild(item);
}
}

window.addEventListener('scroll', () => {
let scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
let startIndex = Math.floor(scrollTop / itemHeight);
let endIndex = startIndex + visibleCount;
render(startIndex, endIndex);
});

// 初始化渲染
render(0, visibleCount);


把CSS里的hover效果移掉,改成鼠标事件动态添加类名,避免全局监听导致重绘。另外,别用transform: scale这种会触发layout的操作,改用更轻量的background-color就够了。
点赞
2026-02-19 10:21