重排重繪與合成


前端有個很經典的問題是說下重排和重繪的區別,一般我們會說重排性能低,而重繪性能高。但其實我們可以深入探究一下其中但原因。

重排(回流)

定義

當通過JS或者 CSS 修改元素的幾何屬性,例如改變元素的寬度、高度等,那么瀏覽器會觸發重新布局,解析之后的一系列子階段,這個過程就叫重排。無疑,重排需要更新完整的渲染流水線,所以開銷也是最大的。

圖示

image.png

觸發條件

  • 添加或者刪除可見的DOM元素
  • 元素位置改變
  • 元素尺寸改變
  • 元素內容改變(例: 一個文本被另一個不同尺寸的圖片替代)
  • 頁面渲染初始化(無法避免)
  • 瀏覽器窗口尺寸改變

優化方案

  1. 盡量不要在布局信息改變時做查詢(會導致渲染隊列強制刷新)。
  2. 合並多次DOM操作。比如用class來改變多個樣式。
  3. 避免使用table。
  4. 使用fragment元素(createDocumentFragment
  5. 讓元素脫離文檔流。即讓當前元素有自己的圖層。
  6. 多次修改時把dom 離線 ,修改完再顯示。(display:none)
  7. 使用采用虛擬DOM的庫,如Vue,React
  8. will-change: transform 啟用硬件加速

 

重繪

定義

當通過JS或者 CSS 修改元素的繪制屬性,例如改變元素的背景顏色,那么布局階段將不會被執行,因為並沒有引起幾何位置的變換,所以就直接進入了繪制階段(即生成待繪制列表),然后執行之后的一系列子階段,這個過程就叫重繪。相較於重排操作,重繪省去了布局和分層階段,所以執行效率會比重排操作要高一些。

圖示

image.png

觸發條件

  • background屬性(background,background-color,background-image,background-position,background-repeat,background-size)
  • outline屬性(outline,outline-color,outline-style)
  • box-shadow屬性
  • border屬性(border-style,border-radius)
  • visibility

優化方案

  1. 合並多次操作

 

合成

定義

更改一個既不要布局也不要繪制的屬性,渲染引擎將跳過布局和繪制,只執行后續的合成操作,我們把這個過程叫做合成。比如我們使用了 CSS 的 transform 來實現動畫效果,這可以避開重排和重繪階段,直接在非主線程上執行合成動畫操作。這樣的效率是最高的,因為是在非主線程上合成,並沒有占用主線程的資源,另外也避開了布局和繪制兩個子階段,所以相對於重繪和重排,合成能大大提升繪制效率。

圖示

image.png

觸發條件

  • will-change
  • transform屬性改變
  • 整個圖層的幾何變換,透明度變換,陰影。

優化方案

  1. 使用will-change提前聲明,使得渲染引擎將該元素單獨實現一幀。(空間換時間)。

⚠️:每當渲染引擎為一個元素准備一個獨立層的時候,它占用的內存也會大大增加,因為從層樹開始,后續每個階段都會多一個層結構,這些都需要額外的內存,所以你需要恰當地使用 will-change。

 

參考:

極客時間:瀏覽器工作原理與實踐

https://blog.csdn.net/qq_42269433/article/details/81133772


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM