回流和重绘

41 阅读2分钟

回流(Reflow)和重绘(Repaint)是浏览器渲染页面时的关键步骤,对性能优化至关重要。以下是它们的核心要点:

1. 回流(Reflow)

  • 定义:当元素的布局属性(如尺寸、位置、结构等)发生变化时,浏览器需要重新计算元素的几何信息,并调整页面布局的过程。
  • 触发条件
    • 改变窗口大小
    • 修改元素尺寸(宽、高、边距等)
    • 增删可见的DOM元素
    • 调整字体或内容变化
    • 激活CSS伪类(如:hover
    • 读取布局属性(如offsetTopscrollWidth等,可能导致强制同步布局)
  • 性能消耗,可能引发整个渲染树重新计算。

2. 重绘(Repaint)

  • 定义:当元素的外观属性(如颜色、背景、边框等)发生变化,但不影响布局时,浏览器重新绘制元素的过程。
  • 触发条件
    • 修改颜色、背景色、边框颜色等
    • 调整透明度(opacity
    • 改变可见性(visibility
  • 性能消耗较低(不涉及布局计算)。

3. 关键区别

  • 回流必然导致重绘:布局变化通常需要重新绘制。
  • 重绘不一定触发回流:仅外观变化且不影响布局时。

4. 优化策略

  • 减少DOM操作
    • 使用DocumentFragment批量操作DOM。
    • 避免逐行修改样式,改用classcssText
  • 避免强制同步布局
    • 避免在修改样式后立即读取布局属性(如offsetTop),这会强制浏览器提前回流。
    • 使用变量缓存布局属性值。
  • 脱离文档流
    • 对动画元素使用position: absolute/fixed,减少布局影响范围。
  • 利用CSS3特性
    • 使用transformopacity实现动画(触发合成层,跳过回流和重绘)。
    • 启用GPU加速(如will-change: transform)。
  • 优化渲染流程
    • 避免使用table布局(局部变化可能引发全局回流)。
    • 使用requestAnimationFrame替代setTimeout处理动画。

5. 浏览器渲染流程

  1. 解析:生成DOM树和CSSOM树。
  2. 合并:构建渲染树(Render Tree)。
  3. 布局(回流):计算元素的位置和尺寸。
  4. 绘制(重绘):填充像素到屏幕。
  5. 合成:将各图层合并显示。

示例

// 不推荐:多次触发回流
element.style.width = '100px';
element.style.height = '200px';

// 推荐:合并修改(一次回流)
element.style.cssText = 'width: 100px; height: 200px;';

总结:优化核心在于减少回流次数和范围,优先使用不影响布局的样式修改,合理利用浏览器渲染机制提升性能。