核心是减少重排与重绘:用DocumentFragment批量操作、合并样式修改、避免强制同步布局、优先使用transform/opacity动画。

避免频繁操作 DOM 导致性能下降,核心是减少浏览器重排(Reflow)和重绘(Repaint)的次数。每次直接修改真实 DOM,尤其是循环中逐个添加、删除或样式变更,都可能触发昂贵的渲染流水线。关键不在“少写 JS”,而在“让每次 DOM 变更更值钱”。
用 DocumentFragment 批量插入节点
循环中反复调用 appendChild 会逐次触发重排——100 次插入 ≈ 100 次重排。DocumentFragment 是内存中的轻量容器,不挂载到真实 DOM,往它里面加节点完全不触发渲染。
- 调用 document.createDocumentFragment() 创建片段
- 所有新节点先 appendChild 到这个片段里
- 最后只执行一次真实父元素的 appendChild(fragment)
这样就把多次重排压缩为 1 次,实测首屏时间可从 800ms 降到约 150ms。
合并样式修改,别逐条赋值
连续写 el.style.width = '100px' 和 el.style.height = '200px',每次赋值都会强制浏览器重新计算样式和布局。
- 改用 el.style.cssText = 'width:100px;height:200px;margin:10px;',一次设完
- 更推荐预定义 CSS 类(如 .card-large),再用 el.classList.add('card-large')
- 类名切换由浏览器底层高效处理,也方便复用和主题管理
避开强制同步布局(Layout Thrashing)
读取 offsetWidth、getComputedStyle、scrollHeight 等属性时,浏览器会立刻完成所有待处理的样式计算和布局,打断 JS 执行流。
- 别在循环里一边改样式一边读尺寸,比如设完 el.style.width 立刻读 el.offsetWidth
- 把所有样式写入操作集中做完,再统一读取;或用 requestAnimationFrame 延迟到下一帧再读
- 能用 CSS 实现的布局(如居中、响应式),尽量不靠 JS 动态算位置或尺寸
动画和高频更新优先用 transform 和 opacity
修改 left/top 或 width/height 会触发布局重排;而 transform(如 translateX)和 opacity 只影响合成层,跳过布局和绘制阶段,由 GPU 直接处理。
- 移动元素用 transform: translateX(100px),不用 left: 100px
- 显隐切换用 opacity: 0 + will-change: opacity,比 display: none 更平滑
- 需要硬件加速时,可提前加 will-change 提示浏览器



















