理解JavaScript中的Repaint和Reflow

最近,在研究React的虛擬DOM如此之快的緣由時,我意識到咱們對javascript性能的瞭解甚少。因此我寫這篇文章是爲了幫助提升對Repaint和Reflow以及JavaScript性能的認識。

Repaint及Reflow

在深刻了解以前,咱們是否瞭解瀏覽器的工做原理呢?

一圖賽過千言萬語,因此讓咱們來了解下瀏覽器的工做原理javascript

瀏覽器工做原理圖
en...那麼什麼是瀏覽器引擎,什麼是渲染引擎呢?html

瀏覽器引擎的主要工做是將Html文檔以及網頁上的其餘資源轉換成交互可視化的視圖,並呈如今用戶設備上。除了瀏覽器引擎,關於相關概念的其餘兩個經常使用術語:「layout engine」和「rendering engine」。理論上,佈局(layout)和渲染(rendering)(或「painting」)能夠由單獨的引擎處理。然而,在實踐中,它們是緊密耦合的,不多單獨考慮。java

理解瀏覽器是怎樣將用戶界面繪製到屏幕上

當咱們點擊頁面上的某個連接或在瀏覽器的URL地址欄按下Enter鍵時,向該頁面發出HTTP請求,而且相應的服務器提供(一般)HTML文檔做爲響應。(二者之間發生了不少事情)。node

1*_alTfrxmTCP1mInn4QEOnA.jpeg

  • 瀏覽器解析HTML源代碼並構造DOM樹,其中每一個HTML標記在樹中具備對應的節點,而且標記之間的文本塊也得到文本節點。DOM樹中的根節點是documentElement(<html>標記)
  • 瀏覽器解析CSS代碼並感知它。樣式信息降級:用戶代理樣式表的基本規則,若有一個用戶樣式表,在做者信息頁面有一個做者樣式表,而後將外部樣式,內聯樣式經過編碼成html標籤的樣式屬性
  • 而後更有趣的部分是構造渲染樹。渲染樹有點像DOM樹,但與DOM樹徹底不匹配。渲染樹知道樣式,因此若是給一個div設置display爲none時,它就不會在渲染樹中呈現出來。其餘不可見元素也是如此,例如head標籤和其中的全部內容。另外一方面,可能有DOM元素在渲染樹中用多個節點表示 - 好比文本節點,例如<p>標籤中的每一行都須要一個渲染節點。渲染樹中的節點稱爲幀或盒子。每個節點有CSS盒子屬性-寬度,高度,邊框,邊距等。
  • 一旦構建了渲染樹,瀏覽器就可以在屏幕上繪製渲染樹節點。瀏覽器

    <html>
    <head>
      <title>Repaint And Reflow</title>
    </head>
    <body>
        
      <p>
        <strong>How's The Josh?</strong>
        <strong><b> High Sir...</b></strong>
      </p>
      
      <div style="display: none">
        Nothing to display
      </div>
      
      <div><img src="..." /></div>
      ...
     
    </body>
    </html>

表示此HTML文檔的DOM樹基本上每一個標記都有一個節點,節點之間的每一個文本都有一個文本節點(爲簡單起見,咱們忽略了空白也是文本節點的事實):服務器

documentElement (html)
        head
            title
        body
            p
                strong
                    [text node]
            p
                strong
                    b
                        [text node]            
            div 
                [text node]
            
            div
                img
            
            ...

渲染樹能夠是DOM樹中可見的部分,它缺乏一些東西 - head和隱藏的div,但它有文本行的附加節點(又名幀,也稱爲盒子)。佈局

root (RenderView)
        body
            p
                line 1
            line 2
            line 3
            ...
            
        div
            img
            
    ...

渲染樹中的根節點包含全部其餘的元素稱爲幀(盒子),咱們能夠將其視爲瀏覽器窗口的內部部分,由於這是頁面能夠傳播的受限區域。從技術上講,WebKit內核調用根節點RenderView,它對應於CSS初始包含塊,它基本上是從頁面頂部(0,0)到(window.innerWidth,window.innerHeight)的視口矩形。性能

Repaint和Reflow

伴隨着繪製,老是有一個初始化頁面。以後,改變用於渲染樹的輸入信息可能由其中一個或兩個所致使(Repaint或Reflow):編碼

  1. 須要從新驗證渲染樹(或整個樹)的部分,並從新計算節點尺寸,這稱爲reflow,或者layout,或者layouting,注意:一個初始頁面至少有一次reflow
  2. 因爲節點幾何屬性的變化或者由於樣式變化(例如更改背景顏色),須要更新屏幕的某些部分,這時屏幕的更新這稱爲repaint或redraw

Repaint和Reflow可能很昂貴,它們可能會損害用戶體驗,並使UI顯得緩慢spa

Repaint

顧名思義,重繪(Repaint)只不過是屏幕上的從新繪製元素,由於元素的變化會影響元素的可見性,但不會影響佈局

如:

  • 改變元素的可見性
  • 改變元素的輪廓
  • 改變元素的背景

均可能觸發重繪(Repaint)

Reflow

重排(Reflow)意味着在文檔中從新去計算元素的位置和幾何形狀。目的是爲了從新渲染文檔的部分或所有。因爲重排在瀏覽器中是用戶行爲阻塞的操做,因此對於開發人員怎樣去提升重排的時間以及瞭解各類文檔屬性(DOM深度,CSS規則效率,不一樣類型的樣式更改)對中排時間的影響是很重要的。

有時,重排文檔中的單個元素可能須要重排其父元素以及其後的任何元素。

相關文章
相關標籤/搜索