前端學習筆記之 瀏覽器如何渲染頁面?

從 HTML 到 DOM

1. 字節流解碼

把字節數據解碼成字符數據的過程。

2. 輸入流預處理

把字符數據進行統一格式化的過程。

3. 令牌化

令牌化包含兩步:第一步是將字符數據轉化成令牌(Token),第二步是解析 HTML 生成 DOM 樹。

html 代碼的標記過程:

  1. 初始化爲“數據狀態”(Data State);
  2. 匹配到字符 <,狀態切換到 “標籤打開狀態”(Tag Open State);
  3. 匹配到字符 !,狀態切換至 “標籤聲明打開狀態”(Markup Declaration Open State),後續 7個字符可以組成字符串 DOCTYPE,跳轉到 “DOCTYPE 狀態”(DOCTYPE State);
  4. 匹配到字符爲空格,當前狀態切換至“DOCTYPE 名稱之前狀態”(Before DOCTYPE Name State);
  5. 匹配到字符串 html,創建一個新的 DOCTYPE 標記,標記的名字爲 “html” ,然後當前狀態切換至 “DOCTYPE 名字狀態”(DOCTYPE Name 之State);
  6. 匹配到字符 >,跳轉到 “數據狀態” 並且釋放當前的 DOCTYPE 標記;
  7. 匹配到字符 <,切換到 “標籤打開狀態”;
  8. 匹配到字符 h,創建一個新的起始標籤標記,設置標記的標籤名爲空,當前狀態切換至 “標籤名稱狀態”(Tag Name State);
  9. 從字符 h 開始解析,將解析的字符一個一個添加到創建的起始標籤標記的標籤名中,直到匹配到字符 >,此時當前狀態切換至 “數據狀態”並釋放當前標記,當前標記的標籤名爲 “html” 。
  10. 解析後續的方式與前面一致,創建並釋放對應的起始標籤標記,解析完畢後,當前狀態處於 “數據狀態” ;
  11. 匹配到字符串 “標記” ,針對每一個字符,創建並釋放一個對應的字符標記,解析完畢後,當前狀態仍然處於 “數據狀態” ;
  12. 匹配到字符 <,進入 “標籤打開狀態” ;
  13. 匹配到字符 /,進入 “結束標籤打開狀態”(End Tag Open State);
  14. 匹配到字符 b,創建一個新的結束標籤標記,設置標記的標籤名爲空,當前狀態切換至“標籤名稱狀態”(Tag Name State);
  15. 重新從字符 b 開始解析,將解析的字符一個一個添加到創建的結束標籤標記的標籤名中,直到匹配到字符 >,此時當前狀態切換至 “數據狀態”並釋放當前標記,當前標記的標籤名爲 “body”;
  16. 解析 的方式與 一樣;
  17. 所有的 html 標籤和文本解析完成後,狀態切換至“數據狀態” ,一旦匹配到文件結束標誌符(EOF),則釋放 EOF 標記。

遇到 script 標籤時的處理:

  • 內聯代碼:解析過程暫停,執行權轉給JavaScript 腳本引擎,等待JavaScript執行完成。如果遇到調用document.write() 函數,此時渲染引擎會回到第二步,將這些代碼加入字符流,重新進行解析。
  • 外鏈腳本:根據標籤屬性來執行對應的操作。

4. 構建 DOM 樹

瀏覽器在創建解析器的同時會創建一個 Document 對象。

構建 DOM 樹的步驟:

  1. 進入初始狀態 “initial” 模式;
  2. 樹構建器接收到 DOCTYPE 令牌後,樹構建器會創建一個 DocumentType節點附加到 Document 節點上,DocumentType 節點的 name 屬性爲 DOCTYPE 令牌的名稱,切換到“before html” 模式;
  3. 接收到令牌 html 後,樹構建器創建一個 html 元素並將該元素作爲 Document的子節點插入到 DOM 樹中和開放元素棧中,切換爲 “before head” 模式;
  4. 雖然沒有接收到 head令牌,但仍然會隱式地創建 head 元素並加到 DOM 樹和開放元素棧中,切換到“in head”模式;
  5. 將開放元素棧中的 head元素彈出,進入 “after head”模式;
  6. 接收到 body 令牌後,會創建一個 body 元素插入到 DOM樹中同時壓入開放元素棧中,當前狀態切換爲 “in body” 模式;
  7. 接收到字符令牌,創建 Text 節點,節點值爲字符內容“標記”,將Text 節點作爲 body 元素節點插入到 DOM 樹中;
  8. 接收到結束令牌 body,將開放元素棧中的 body 元素彈出,切換“after body” 模式;
  9. 接收到結束令牌 html,將開放元素棧中的 html 元素彈出,切換至 “after after body” 模式;
  10. 接收到 EOF 令牌,樹構建器停止構建,html 文檔解析過程完成。

從 DOM 到渲染

有了 DOM 樹和 CSSOM 樹之後,渲染引擎就可以開始生成頁面了。

5. 構建渲染樹

將DOM 樹包含的結構內容與 CSSOM 樹包含的樣式規則合併成一棵渲染樹。這個過程會從 DOM 樹的根節點開始遍歷,然後在 CSSOM 樹上找到每個節點對應的樣式。

6. 佈局

佈局就是計算元素的大小及位置。
佈局完成後會輸出對應的“盒模型”,它會精確地捕獲每個元素的確切位置和大小,將所有相對值都轉換爲屏幕上的絕對像素。

7. 繪製

繪製就是將渲染樹中的每個節點轉換成屏幕上的實際像素的過程。

總結

瀏覽器渲染引擎生成頁面的 7 個步驟,前面 4 個步驟爲 DOM 樹的生成過程,後面 3 個步驟是利用 DOM 樹和 CSSOM 樹來渲染頁面的過程。數據的變化過程歸結如下:

字節 → 字符 → 令牌 → 樹 → 頁面

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章