重排(Reflow)和重绘(Repaint)的区别?

0 阅读2分钟

一、核心区别一句话总结

👉 Reflow(重排) = 改变了布局(几何信息)
👉 Repaint(重绘) = 只改外观,不影响布局


二、什么是 Reflow(重排)

定义:
当 DOM 元素的几何属性发生变化,浏览器需要重新计算布局(位置 + 大小),这个过程叫 重排

常见触发场景

  • 改变元素尺寸

    div.style.width = '200px'
    
  • 改变位置

    div.style.marginLeft = '20px'
    
  • 添加 / 删除 DOM

    parent.appendChild(child)
    
  • 改变字体大小

  • 浏览器窗口 resize

  • 读取某些属性(会强制重排)

    div.offsetWidth
    

特点

  • 开销大(性能杀手)
  • ❗ 会影响其他元素(连锁反应)
  • ❗ 一定会触发 repaint

三、什么是 Repaint(重绘)

定义:
当元素的外观发生变化,但不影响布局时,浏览器只需要重新绘制。

常见触发场景

  • 改颜色

    div.style.color = 'red'
    
  • 改背景

    div.style.background = 'blue'
    
  • 改阴影、透明度

    div.style.opacity = 0.5
    

特点

  • ✅ 开销比 reflow 小
  • ✅ 不影响布局
  • ❗ 只在当前元素生效

四、流程关系(非常重要)

浏览器渲染流程:

DOM -> CSSOM -> Render Tree -> Layout -> Paint
                         ↑        ↑
                      Reflow   Repaint

👉 Reflow 发生在 Layout 阶段
👉 Repaint 发生在 Paint 阶段


五、关系总结(面试重点)

对比ReflowRepaint
是否影响布局✅ 是❌ 否
开销❌ 大✅ 小
是否影响其他元素✅ 会❌ 不会
是否触发 repaint✅ 一定会❌ 不一定触发 reflow

六、经典面试加分点(优化建议)

1. 减少重排次数

// ❌ 多次操作 DOM
div.style.width = '100px'
div.style.height = '100px'

// ✅ 合并操作
div.style.cssText = 'width:100px;height:100px'

2. 脱离文档流操作

// 使用 display:none
div.style.display = 'none'
// 修改
div.style.width = '200px'
div.style.display = 'block'

3. 使用 DocumentFragment

const frag = document.createDocumentFragment()

4. 避免频繁读取布局信息

// ❌ 读写交替(触发多次 reflow)
div.style.width = '100px'
console.log(div.offsetWidth)

5. 使用 transform 替代 top/left

// ❌ 触发 reflow
div.style.left = '100px'

// ✅ 只触发 repaint(甚至走 GPU)
div.style.transform = 'translateX(100px)'

七、一个形象理解

👉 把页面当成一张纸:

  • Reflow = 重新排版(段落、位置全变)
  • Repaint = 只是重新上色

八、面试标准回答模板(直接背)

Reflow 是指 DOM 元素的几何属性发生变化,浏览器需要重新计算布局,会影响其他元素,性能开销较大;
Repaint 是指元素样式变化但不影响布局,只进行重绘,性能开销较小;
并且 Reflow 一定会引起 Repaint,但 Repaint 不一定触发 Reflow。