重繪及迴流

瀏覽器的渲染過程

  1. 解析HTML,生成DOM樹,解析CSS,生成CSSOM樹
  2. 將DOM樹和CSSOM樹結合,生成渲染樹(Render Tree)
  3. Layout(迴流):根據生成的渲染樹,進行迴流(Layout),獲得節點的幾何信息(位置,大小)
  4. Painting(重繪):根據渲染樹以及迴流獲得的幾何信息,獲得節點的絕對像素
  5. Display:將像素髮送給GPU,展現在頁面上。

爲了構建渲染樹,瀏覽器主要完成了如下工做:css

  1. 從DOM樹的根節點開始遍歷每一個可見節點。
  2. 對於每一個可見的節點,找到CSSOM樹中對應的規則,並應用它們。
  3. 根據每一個可見節點以及其對應的樣式,組合生成渲染樹。

第一步中,既然說到了要遍歷可見的節點,那麼咱們得先知道,什麼節點是不可見的。不可見的節點包括:css3

  1. 一些不會渲染輸出的節點,好比script、meta、link等。
  2. 一些經過css進行隱藏的節點。好比display:none。注意,利用visibility和opacity隱藏的節點,仍是會顯示在渲染樹上的。只有display:none的節點纔不會顯示在渲染樹上。

迴流

前面咱們經過構造渲染樹,咱們將可見DOM節點以及它對應的樣式結合起來,但是咱們還須要計算它們在設備視口(viewport)內的確切位置和大小,這個計算的階段就是迴流。瀏覽器

重繪

最終,咱們經過構造渲染樹和迴流階段,咱們知道了哪些節點是可見的,以及可見節點的樣式和具體的幾何信息(位置、大小),那麼咱們就能夠將渲染樹的每一個節點都轉換爲屏幕上的實際像素,這個階段就叫作重繪節點。緩存

什麼時候發生迴流

迴流這一階段主要是計算節點的位置和幾何信息,那麼當頁面佈局和幾何信息發生變化的時候,就須要迴流。好比如下狀況:ide

  1. 添加或刪除可見的DOM元素
  2. 元素的位置發生變化
  3. 元素的尺寸發生變化(包括外邊距、內邊框、邊框大小、高度和寬度等)
  4. 內容發生變化,好比文本變化或圖片被另外一個不一樣尺寸的圖片所替代。
  5. 頁面一開始渲染的時候(這確定避免不了)
  6. 瀏覽器的窗口尺寸變化(由於迴流是根據視口的大小來計算元素的位置和大小的)

瀏覽器的優化機制

現代的瀏覽器都是很聰明的,因爲每次重排都會形成額外的計算消耗,所以大多數瀏覽器都會經過隊列化修改並批量執行來優化重排過程。瀏覽器會將修改操做放入到隊列裏,直到過了一段時間或者操做達到了一個閾值,才清空隊列。可是!當你獲取佈局信息的操做的時候,會強制隊列刷新,好比當你訪問如下屬性或者使用如下方法:佈局

  1. offsetTop、offsetLeft、offsetWidth、offsetHeight
  2. scrollTop、scrollLeft、scrollWidth、scrollHeight
  3. clientTop、clientLeft、clientWidth、clientHeight
  4. getComputedStyle()
  5. getBoundingClientRect

減小重繪與迴流

CSS

  1. 使用 transform 替代 top
  2. 使用 visibility 替換 display: none ,由於前者只會引發重繪,後者會引起迴流(改變了佈局
  3. 避免使用table佈局,可能很小的一個小改動會形成整個 table 的從新佈局。
  4. 儘量在DOM樹的最末端改變class,迴流是不可避免的,但能夠減小其影響。儘量在DOM樹的最末端改變class,能夠限制了迴流的範圍,使其影響儘量少的節點。
  5. 避免設置多層內聯樣式,CSS 選擇符從右往左匹配查找,避免節點層級過多。
  6. 將動畫效果應用到position屬性爲absolute或fixed的元素上,避免影響其餘元素的佈局,這樣只是一個重繪,而不是迴流,同時,控制動畫速度能夠選擇 requestAnimationFrame,詳見探討 requestAnimationFrame。
  7. 避免使用CSS表達式,可能會引起迴流。
  8. 將頻繁重繪或者回流的節點設置爲圖層,圖層可以阻止該節點的渲染行爲影響別的節點,例如will-change、video、iframe等標籤,瀏覽器會自動將該節點變爲圖層。
  9. CSS3 硬件加速(GPU加速),使用css3硬件加速,可讓transform、opacity、filters這些動畫不會引發迴流重繪 。優化

    JavaScript

  10. 避免頻繁操做樣式,最好一次性重寫style屬性,或者將樣式列表定義爲class並一次性更改class屬性。
  11. 避免頻繁操做DOM,建立一個documentFragment,在它上面應用全部DOM操做,最後再把它添加到文檔中。
  12. 避免頻繁讀取會引起迴流/重繪的屬性,若是確實須要屢次使用,就用一個變量緩存起來。
  13. 對具備複雜動畫的元素使用絕對定位,使它脫離文檔流,不然會引發父元素及後續元素頻繁迴流。
相關文章
相關標籤/搜索