瀏覽器的迴流和重繪及其優化方式

推薦瞭解的知識:基本的HTML,基本的JavaScript,以及一些css工做原理方面的知識css

瀏覽器的渲染原理

  • css的加載和解析不會阻塞html文檔的解析
  • css的解析會阻塞js的執行,必須等到CSSOM生成後才能執行js
  • js的執行會阻塞html文檔的解析
  • html一邊解析一邊顯示
  • css必須徹底解析完畢才能進入生成渲染樹環節
           瀏覽器向服務器請求到了HTML文檔後便開始解析,產物是DOM Tree(文檔對象模型),若是有css,會根據css生成CSSOM(CSS對象模型),而後再由DOM和CSSOM合併產生Render Tree渲染樹,有了渲染樹,知道了全部節點的樣式,便根據這些節點以及樣式計算它們在瀏覽器中確切的大小和位置,這就是佈局。最後把節點繪製到瀏覽器上。

clipboard.png

建立DOM樹—建立CSSOM樹—執行腳本—生成渲染樹—生成佈局—繪製html

迴流

       迴流(reflow)當render tree中的一部分(或所有)由於元素的規模尺寸,佈局,隱藏等改變時,網絡瀏覽器從新渲染部分或所有文檔的過程。node

重繪

       當頁面元素樣式改變不影響元素在文檔流中的位置時(如background-color,border-color,visibility),瀏覽器只會將新樣式賦予元素並進行從新繪製操做。瀏覽器

       由於迴流(reflow)在瀏覽器中屬於一種用戶主導的模塊化操做,因此知道如何去改進迴流(reflow)時間以及知道各類文檔屬性(DOM節點深度,css的渲染效率,各類各樣的樣式改變)對迴流(reflow)時間的影響對於開發人員講是頗有幫助的。有時候,即便僅僅迴流一個單一的元素,也可能要求它的父元素以及任何跟隨它的元素也產生迴流。性能優化

什麼時候發生

       有大量的用戶行爲以及潛在的DHTML改變會觸發迴流(reflow)。例如,改變瀏覽器窗口的大小,使用一些JavaScript方法,包括計算樣式,對DOM進行元素的添加或刪除,或是改變元素的class等。服務器

  1. 添加或者刪除可見的DOM元素;
  2. 元素位置改變;
  3. 元素尺寸改變——邊距、填充、邊框、寬度和高度
  4. 內容變化,好比用戶在input框中輸入文字,文本或者圖片大小改變而引發的計算值寬度和高度改變
  5. 頁面渲染初始化
  6. 瀏覽器窗口尺寸改變——resize事件發生時
  7. 計算 offsetWidth 和 offsetHeight 屬性
  8. 設置 style 屬性的值

       迴流必將引發重繪,而重繪不必定會引發迴流。網絡

性能優化

       迴流比重繪的代價要更高,迴流的花銷跟render tree有多少節點須要從新構建有關係;瀏覽器自己可以進行優化,儘量減小重繪和迴流。
       若是每行JS代碼操做DOM都須要迴流重繪的話,瀏覽器可能就會受不了。因此不少瀏覽器都會優化這些操做,瀏覽器會維護1個隊列,把全部會引發迴流、重繪的操做放入這個隊列,等隊列中的操做到了必定的數量或者到了必定的時間間隔,瀏覽器就會flush隊列,進行一個批處理。這樣就會讓屢次的迴流、重繪變成一次迴流重繪。
       當你請求向瀏覽器請求一些 style信息的時候,就會讓瀏覽器flush隊列,好比:app

  1. offsetTop, offsetLeft, offsetWidth, offsetHeight
  2. scrollTop/Left/Width/Height
  3. clientTop/Left/Width/Height
  4. width,height
  5. 請求了getComputedStyle(), 或者 IE的 currentStyle

       當你請求上面的一些屬性的時候,瀏覽器爲了給你最精確的值,須要flush隊列,由於隊列中可能會有影響到這些值的操做。即便你獲取元素的佈局和樣式信息跟最近發生或改變的佈局信息無關,瀏覽器都會強行刷新渲染隊列。模塊化

如何減小回流、重繪

var s = document.body.style; 

s.padding = "2px"; // 迴流+重繪

s.border = "1px solid red"; // 再一次 迴流+重繪

s.color = "blue"; // 再一次重繪

s.backgroundColor = "#ccc"; // 再一次 重繪

s.fontSize = "14px"; // 再一次 迴流+重繪

// 添加node,再一次 迴流+重繪
document.body.appendChild(document.createTextNode('abc!'));

///能夠看到每次DOM元素的樣式操做都會引起重繪,若是涉及佈局還會引起迴流。

一. CSS中避免迴流wordpress

  1. 儘量在DOM樹的最末端改變class
  2. 避免設置多層內聯樣式
  3. 動畫效果應用到position屬性爲absolute或fixed的元素上
  4. 犧牲平滑度換取速度
  5. 避免使用table佈局
  6. 避免使用CSS的JavaScript表達式

二. JS操做避免迴流

  1. 避免逐項更改樣式。最好一次性更改style屬性,或者將樣式列表定義爲class並一次性更改class屬性。
  2. 避免循環操做DOM。建立一個documentFragment或div,在它上面應用全部DOM操做,最後再把它添加到window.document。
  3. 也能夠在一個display:none的元素上進行操做,最終把它顯示出來。由於display:none上的DOM操做不會引起迴流和重繪。
  4. 避免循環讀取offsetLeft等屬性。在循環以前把它們存起來。
  5. 絕對定位具備複雜動畫的元素。絕對定位使它脫離文檔劉,不然會引發父元素及後續元素大量的迴流。

參考文章:迴流與重繪:CSS性能讓JavaScript變慢?
參考文章:瀏覽器的重繪(repaints)與重排(reflows)

相關文章
相關標籤/搜索