国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频

【W(wǎng)eb技術(shù)】1151- 重排、重繪、合成,你真的懂嗎?

共 3977字,需瀏覽 8分鐘

 ·

2021-11-27 12:46

前言

  • 重排、重繪、合成是什么?總的來說,它們都是瀏覽器渲染頁面進(jìn)程中的一個小小的環(huán)節(jié),正是這些小環(huán)節(jié)按照一定的規(guī)則有條不紊的運作,才保證了我們能正常、順暢地網(wǎng)上沖浪。
  • 本文主要介紹了重排、重繪、合成的基本概念、觸發(fā)時機(jī)、影響范圍以及其優(yōu)化策略。
  • 我們首先來看一下,瀏覽器的渲染原理,看一下,它們分別擔(dān)任了什么工作?

一、瀏覽器渲染原理

結(jié)合上圖,一個完整的渲染流程大致可總結(jié)為如下幾個步驟:

  1. HTML被HTML解析器解析成DOM Tree
  2. CSS則被CSS解析器解析成CSSOM Tree
  3. DOM Tree和CSSOM Tree解析完成后,被附加到一起,形成渲染樹(Render Tree)
  4. 布局,根據(jù)渲染樹計算每個節(jié)點的幾何信息生成布局樹(Layout Tree)
  5. 對布局樹進(jìn)行分層,并生成分層樹(Layer Tree)
  6. 為每個圖層生成繪制列表
  7. 渲染繪制(Paint)。根據(jù)計算好的繪制列表信息繪制整個頁面,并將其提交到合成線程
  8. 合成線程將圖層分成圖塊,并在光柵化線程池中將圖塊轉(zhuǎn)換成位圖,發(fā)送繪制圖塊命令 DrawQuad 給瀏覽器進(jìn)程
  9. 瀏覽器進(jìn)程根據(jù) DrawQuad 消息生成頁面,并顯示到顯示器上

二、重排

  1. 定義:當(dāng)通過JS或css改變了元素的寬度、高度等,修改了元素的幾何位置屬性,那么瀏覽器會觸發(fā)重新布局,解析之后的一系列子階段,這個過程就叫重排。無疑,重排需要更新完整的渲染流水線,所以開銷也是最大的。

  2. 觸發(fā)時機(jī)和影響范圍:DOM節(jié)點信息更改,觸發(fā)重排時,這個DOM更改程度會決定周邊DOM更改范圍。

    • 全局范圍:就是從根節(jié)點html開始對整個渲染樹進(jìn)行重新布局,例如當(dāng)我們改變了窗口尺寸或方向或者是修改了根元素的尺寸或者字體大小等。
    • 局部范圍:對渲染樹的某部分或某一個渲染對象進(jìn)行重新布局。

三、重繪

  1. 定義:如果修改了元素的背景顏色,并沒有引起幾何位置的變換,所以就直接進(jìn)入了繪制階段,然后執(zhí)行之后的一系列子階段,這個過程就叫重繪。相較于重排操作,重繪省去了布局和分層階段,所以執(zhí)行效率會比重排操作要高一些。

  2. 觸發(fā)時機(jī)和影響范圍:每一次的dom更改或者css幾何屬性更改,都會引起一次瀏覽器的重排/重繪過程,而如果是css的非幾何屬性更改,則只會引起重繪過程。所以說重排一定會引起重繪,而重繪不一定會引起重排,重繪的開銷較小,重排的代價較高。

四、合成

  1. 定義:合成是一種將頁面的各個部分分離成層(Layer Tree),分別將它們柵格化,然后在稱為“合成線程”的中組合為頁面的技術(shù)。

  2. 觸發(fā)時機(jī)和影響范圍:在GUI渲染線程后執(zhí)行,將GUI渲染線程生成的繪制列表轉(zhuǎn)換為位圖,然后發(fā)送繪制圖塊命令 DrawQuad 給瀏覽器進(jìn)程,瀏覽器進(jìn)程根據(jù) DrawQuad 消息生成頁面,將頁面顯示到顯示器上

  3. 優(yōu)點:我們使用了 CSS 的 transform 來實現(xiàn)動畫效果,避開了重排和重繪階段,直接在非主線程上執(zhí)行合成動畫操作。這樣的效率是最高的,因為是在非主線程上合成,并沒有占用主線程的資源,另外也避開了布局和繪制兩個子階段,所以相對于重繪和重排,合成能大大提升繪制效率。

五、常見的觸發(fā)重排、重繪的屬性和方法

  1. 常見的觸發(fā)重排、重繪的屬性和方法

  1. 全局范圍重排、局部范圍重排、重繪的影響范圍示例

六、優(yōu)化策略

6.1 減少DOM操作

  1. 最小化DOM訪問次數(shù),盡量緩存訪問DOM的樣式信息,避免過度觸發(fā)重排。
  2. 如果在一個局部方法中需要多次訪問同一個dom,可以在第一次獲取元素時用變量保存下來,減少遍歷時間。
  3. 用事件委托來減少事件處理器的數(shù)量。
  4. 用querySelectorAll()替代getElementByXX()。
  • querySelectorAll():獲取靜態(tài)集合,通過函數(shù)獲取元素之后,元素之后的改變并不會影響之前獲取后存儲到的變量。也就是獲取到元素之后就和html中的這個元素沒有關(guān)系了
  • getElementByXX():獲取動態(tài)集合,通過函數(shù)獲取元素之后,元素之后的改變還是會動態(tài)添加到已經(jīng)獲取的這個元素中。換句話說,通過這個方法獲取到元素存儲到變量的時候,以后每一次在Javascript函數(shù)中使用這個變量的時候都會再去訪問一下這個變量對應(yīng)的html元素。

6.2 減少重排

  1. 放棄傳統(tǒng)操作DOM的時代,基于vue/react開始數(shù)據(jù)影響視圖模式。
  2. 避免設(shè)置大量的style內(nèi)聯(lián)屬性,因為通過設(shè)置style屬性改變結(jié)點樣式的話,每一次設(shè)置都會觸發(fā)一次reflow,所以最好是使用class屬性。
  3. 不要使用table布局,因為table中某個元素一旦觸發(fā)了reflow,那么整個table的元素都會觸發(fā)reflow。那么在不得已使用table的場合,可以設(shè)置table-layout:auto;或者是table-layout:fixed這樣可以讓table一行一行的渲染,這種做法也是為了限制reflow的影響范圍。
  4. 盡量少使用display:none可以使用visibility:hidden代替,display:none會造成重排,visibility:hidden只會造成重繪。
  5. 使用resize事件時,做防抖和節(jié)流處理。
  6. 分離讀寫操作(現(xiàn)代的瀏覽器都有渲染隊列的機(jī)制)
  • 分離讀寫減少重排的原理