前言
面試官:既然你剛剛提到了重繪和重排,那就說一說吧。
我:。。。💥
我們首先來回顧一下
渲染流水線
的流程:
回流
首先介紹
回流
。
回流
也叫
重排
。
觸發條件
簡單來說,就是當我們對 DOM 結構的修改引發
DOM 幾何尺寸變化
的時候,會發生
回流
的過程。比如以下情況
- 一個 DOM 元素的幾何屬性變化,常見的幾何屬性有
、width
、height
、padding
、margin
、left
、top
等等, 這個很好了解。border
- 使 DOM 節點發生
或者增減
。移動
- 讀寫
族、offset
族和scroll
族屬性的時候,浏覽器為了擷取這些值,需要進行回流操作。client
- 調用
方法。window.getComputedStyle
回流過程
依照上面的渲染流水線,觸發回流的時候,如果 DOM 結構發生改變,則重新渲染 DOM 樹,然後将後面的流程(包括主線程之外的任務)全部走一遍。
相當于将解析和合成的過程重新又走了一遍,開銷是非常大的。
重繪
觸發條件
當 DOM 的修改導緻了
樣式的變化
,并且
沒有影響幾何屬性的時候
,會導緻
重繪
(
repaint
)。
重繪過程
由于沒有導緻 DOM 幾何屬性的變化,是以元素的位置資訊不需要更新,進而省去布局的過程。流程如下:
跳過了
生成布局樹
和
建圖層樹
的階段,直接生成繪制清單,然後繼續進行分塊、生成位圖等後面一系列操作。
是以說:
重繪不一定導緻回流,但回流一定發生了重繪
。
合成
這是我們可能不太熟悉的一種情況,是
直接合成
。比如利用 CSS3 的
transform
、
opacity
、
filter
這些屬性就可以實作合成的效果,也就是大家常說的GPU加速。
GPU加速的原因
在合成的情況下,會直接跳過布局和繪制流程,直接進入
非主線程
處理的部分,即直接交給
合成線程
處理。交給它處理有兩大好處:
- 能夠充分發揮
的優勢。合成線程生成位圖的過程中會調用線程池,并在其中使用GPU
進行加速生成,而GPU 是擅長處理位圖資料的。GPU
- 沒有占用主線程的資源,即使主線程卡住了,效果依然能夠流暢地展示。
總結
知道上面的原理之後,對于開發過程有什麼指導意義呢?
- 避免頻繁使用 style,而是采用修改
的方式。class
- 使用
進行批量的 DOM 操作。createDocumentFragment
- 對于 resize、scroll 等進行防抖/節流處理。
- 添加 will-change: tranform ,讓渲染引擎為其單獨實作一個圖層,當這些變換發生時,僅僅隻是利用合成線程去處理這些變換,而不牽扯到主線程,大大提高渲染效率。當然這個變化不限于
, 任何可以實作合成效果的 CSS 屬性都能用tranform
來聲明。will-change