[浏览器知识点] 重排 重绘 合成

590 阅读2分钟

有了前面渲染流水线的基础,我们来看看三个和渲染流水线相关的概念“重排”“重绘”“合成”。

更新了元素的几何属性(重排)

可以参考下图:

image.png 从上图可以看出,如果你通过 JavaScript 或者 CSS 修改元素的几何位置属性,例如改变元素的宽度、高度等,那么浏览器会触发重新布局,解析之后的一系列子阶段,这个过程就叫重排。无疑,重排需要更新完整的渲染流水线,所以开销也是最大的

更新元素的绘制属性(重绘)

比如通过JavaScript更改某些元素的背景颜色,那么布局阶段不会被执行,因为没有引起几何位置的变换,所以就直接进入绘制阶段,然后执行之后的一系列子阶段,这个过程叫做重绘。相较于重排操作,重绘省去了布局和分层阶段,所以执行效率回比重排操作更高一些

image.png

直接合成阶段

如果更改一个既不要布局也不要绘制的属性(比如CSS3的实现的一些动画效果),渲染引擎将跳过布局和绘制,只执行后续的合成操作,我们把这个过程叫做合成。具体流程参考下图:

image.png 在上图中,我们使用了 CSS 的 transform 来实现动画效果,这可以避开重排和重绘阶段,直接在非主线程上执行合成动画操作。这样的效率是最高的,因为是在非主线程上合成,并没有占用主线程的资源,另外也避开了布局和绘制两个子阶段,所以相对于重绘和重排,合成能大大提升绘制效率

减少重绘、重排?

  1. 使用 class 操作样式,而不是频繁操作 style
  2. 避免使用 table 布局
  3. 批量dom 操作,例如 createDocumentFragment,或者使用框架,例如 React
  4. Debounce window resize 事件
  5. 对 dom 属性的读写要分离
  6. will-change: transform 做优化

参考文献