瀏覽器渲染頁面

HTML解析器輸出的樹是由DOM元素和屬性節點組成的,它是HTML文檔的對象化描述,也是HTML元素與外界(如Javascript)的接口。DOM與標籤有着幾乎一一對應的關係。 javascript

  DOM樹的構建過程爲:將字節轉換成字符,肯定tokens,將tokens轉換成節點,而後構建 DOM 樹。css

瀏覽器構建這個簡單頁面的 DOM 過程當中,在文檔的 head 中遇到了一個 link 標記,該標記引用一個外部 CSS 樣式表:style.css。因爲預見到須要利用該資源來渲染頁面,它會當即發出對該資源的請求。並進行CSSDOM樹的構建。html

CSSOM 樹和 DOM 樹合併成渲染樹,而後用於計算每一個可見元素的佈局,並輸出給繪製流程,將像素渲染到屏幕上。java

繪製過程以下:node

>瀏覽器

  • DOM 樹與 CSSOM樹合併後造成渲染樹,它只包含渲染網頁所需的節點。遍歷每一個DOM樹中的node節點,在CSSOM規則樹中尋找當前節點的樣式,生成渲染樹。
  • 佈局計算每一個對象的精確位置和大小。
  • 最後一步是繪製,使用最終渲染樹將像素渲染到屏幕上。

那麼當資源中還有js時會發生什麼?答案是阻塞DOM樹的構建! 異步

腳本在文檔的何處插入,就在何處執行。當 HTML 解析器遇到一個 script 標記時,它會暫停構建 DOM,將控制權移交給 JavaScript 引擎;等 JavaScript 引擎運行完畢,瀏覽器會從中斷的地方恢復 DOM 構建。而所以就會推遲頁面首繪的時間。async

提到首繪這裏來提兩個概念:DOMContentLoaded和load佈局

1.當 onload 事件觸發時,頁面上全部的DOM,樣式表,腳本,圖片,flash都已經加載完成了。 
2.當 DOMContentLoaded 事件觸發時,僅當DOM加載完成,不包括樣式表,圖片,flash。動畫

頁面的首次繪製是在渲染樹解析構建完畢以後。所以所需的關鍵資源是構建DOM樹和CSSDOM的html和css。可是當執行js時會阻塞html的解析也就推遲了頁面的首繪時間。該如何解決這個問題呢? 
能夠在首繪不須要js的狀況下用async和defer實現異步加載。這樣就js就不會阻塞html的解析了。注意,異步執行是指下載。執行js時仍然會阻塞。

<script async src="siteScript.js" onload="myInit()"></script> <script defer src="siteScript.js" onload="myInit()"></script> 

以上兩種方式均可以實現js的異步加載。那麼二者之間有什麼區別呢?

  • async 腳本在script文件下載完成後會當即執行,而且其執行時間必定在 window的load事件觸發以前。這意味着多個async腳本極可能不會按其在頁面中的出現次序順序執行。
  • 與此相對,瀏覽器確保多個 defer 腳本按其在HTML頁面中的出現順序依次執行,且執行時機爲DOM解析完成後,document的DOMContentLoaded 事件觸發以前。

  因爲async腳本執行順序的不肯定性所以不能用來加載具備明顯依賴關係的js會形成亂序。

DOM樹表示頁面結構,渲染樹表示DOM節點如何顯示。DOM樹中的每個須要顯示的節點在渲染樹種至少存在一個對應的節點(隱藏的DOM元素disply值爲none 在渲染樹中沒有對應的節點)。

渲染樹中的節點被稱爲「幀」或「盒」,符合CSS模型的定義,理解頁面元素爲一個具備填充,邊距,邊框和位置的盒子。一旦DOM和渲染樹構建完成,瀏覽器就開始顯示(繪製)頁面元素。

那麼什麼是重排和重繪呢 
當DOM的變化影響了元素的幾何屬性(寬或高),瀏覽器須要從新計算元素的幾何屬性,一樣其餘元素的幾何屬性和位置也會所以受到影響。

瀏覽器會使渲染樹中受到影響的部分失效,並從新構造渲染樹。這個過程稱爲重排。完成重排後,瀏覽器會從新繪製受影響的部分到屏幕,該過程稱爲重繪。

因爲瀏覽器的流佈局,對渲染樹的計算一般只須要遍歷一次就能夠完成。但table及其內部元素除外,它可能須要屢次計算才能肯定好其在渲染樹中節點的屬性,

一般要花3倍於同等元素的時間。這也是爲何咱們要避免使用table作佈局的一個緣由。

並非全部的DOM變化都會影響幾何屬性,好比改變一個元素的背景色並不會影響元素的寬和高,這種狀況下只會發生重繪。 
由於重排和重繪的耗時是巨大的因此應當儘量減小重排和重繪。

一、儘可能不要在佈局信息改變時作查詢(會致使渲染隊列強制刷新) 二、同一個DOM的多個屬性改變能夠寫在一塊兒(減小DOM訪問,同時把強制渲染隊列刷新的風險降爲0) 三、若是要批量添加DOM,能夠先讓元素脫離文檔流,操做完後再帶入文檔流,這樣只會觸發一次重排(fragment元素的應用) 四、 將須要屢次重排的元素,position屬性設爲absolute或fixed,這樣此元素就脫離了文檔流,它的變化不會影響到其餘元素。例若有動畫效果的元素就最好設置爲絕對定位。

相關文章
相關標籤/搜索