天天看点

☀️什么是重绘和重排? 如何去避免?

☀️什么是重绘和重排? 如何去避免?

前言

面试官:既然你刚刚提到了重绘和重排,那就说一说吧。

我:。。。💥

我们首先来回顾一下

渲染流水线

的流程:

☀️什么是重绘和重排? 如何去避免?

回流

首先介绍

回流

回流

也叫

重排

触发条件

简单来说,就是当我们对 DOM 结构的修改引发

DOM 几何尺寸变化

的时候,会发生

回流

的过程。比如以下情况

  1. 一个 DOM 元素的几何属性变化,常见的几何属性有

    width

    height

    padding

    margin

    left

    top

    border

    等等, 这个很好理解。
  2. 使 DOM 节点发生

    增减

    或者

    移动

  3. 读写

    offset

    族、

    scroll

    族和

    client

    族属性的时候,浏览器为了获取这些值,需要进行回流操作。
  4. 调用

    window.getComputedStyle

    方法。

回流过程

依照上面的渲染流水线,触发回流的时候,如果 DOM 结构发生改变,则重新渲染 DOM 树,然后将后面的流程(包括主线程之外的任务)全部走一遍。

☀️什么是重绘和重排? 如何去避免?

相当于将解析和合成的过程重新又走了一遍,开销是非常大的。

重绘

触发条件

当 DOM 的修改导致了

样式的变化

,并且

没有影响几何属性的时候

,会导致

重绘

(

repaint

)。

重绘过程

由于没有导致 DOM 几何属性的变化,因此元素的位置信息不需要更新,从而省去布局的过程。流程如下:

☀️什么是重绘和重排? 如何去避免?

跳过了

生成布局树

建图层树

的阶段,直接生成绘制列表,然后继续进行分块、生成位图等后面一系列操作。

所以说:

重绘不一定导致回流,但回流一定发生了重绘

合成

这是我们可能不太熟悉的一种情况,是

直接合成

。比如利用 CSS3 的

transform

opacity

filter

这些属性就可以实现合成的效果,也就是大家常说的GPU加速。

GPU加速的原因

在合成的情况下,会直接跳过布局和绘制流程,直接进入

非主线程

处理的部分,即直接交给

合成线程

处理。交给它处理有两大好处:

  1. 能够充分发挥

    GPU

    的优势。合成线程生成位图的过程中会调用线程池,并在其中使用

    GPU

    进行加速生成,而GPU 是擅长处理位图数据的。
  2. 没有占用主线程的资源,即使主线程卡住了,效果依然能够流畅地展示。

总结

知道上面的原理之后,对于开发过程有什么指导意义呢?

  1. 避免频繁使用 style,而是采用修改

    class

    的方式。
  2. 使用

    createDocumentFragment

    进行批量的 DOM 操作。
  3. 对于 resize、scroll 等进行防抖/节流处理。
  4. 添加 will-change: tranform ,让渲染引擎为其单独实现一个图层,当这些变换发生时,仅仅只是利用合成线程去处理这些变换,而不牵扯到主线程,大大提高渲染效率。当然这个变化不限于

    tranform

    , 任何可以实现合成效果的 CSS 属性都能用

    will-change

    来声明。

继续阅读