摘要:渲染引擎的概述渲染引擎的主要職責是在瀏覽器屏幕上顯示請求的頁面。中,渲染樹中的每個節點都被稱為的渲染器或渲染對象。坐標系相對于根渲染器。增量只有一些渲染器以不影響整個樹的方式進行更改。渲染器使其矩形在屏幕上無效。
到目前為止,在我們之前的“JavaScript工作原理”系列文章中,我們一直關注JavaScript作為一種語言,其功能,它如何在瀏覽器中執行,如何優化等等。
但是,當您構建Web應用程序時,您不只是編寫獨立運行的獨立JavaScript代碼。您編寫的JavaScript與環境進行交互。了解這種環境,它是如何工作的以及它的組成是什么,將使您能夠構建更好的應用程序,并對應用程序發布后可能出現的潛在問題做好充分準備。
那么,讓我們看看瀏覽器的主要組件是什么:
用戶界面:這包括地址欄,后退和前進按鈕,書簽菜單等。實質上,這是瀏覽器顯示的每個部分,除了您看到網頁本身的窗口。
瀏覽器引擎:它處理用戶界面和渲染引擎之間的交互
渲染引擎:它負責顯示網頁。渲染引擎解析HTML和CSS,并在屏幕上顯示解析的內容。
網絡:這些是網絡調用,例如XHR請求,通過對不同平臺使用不同的實現來實現,這些平臺位于獨立于平臺的接口之后。在本系列的前一篇文章中,我們更詳細地討論了網絡層。
UI后端:用于繪制核心小部件,如復選框和窗口。這個后端公開了一個不是平臺特定的通用接口。它使用下面的操作系統UI方法。
JavaScript引擎:我們在該系列的前一篇文章中詳細介紹了這一點。基本上,這是JavaScript執行的地方。
數據持久性:您的應用可能需要在本地存儲所有數據。支持的存儲機制類型包括localStorage,indexDB,WebSQL和FileSystem。
在這篇文章中,我們將關注渲染引擎,因為它處理HTML和CSS的解析和可視化,這是大多數JavaScript應用程序不斷與之交互的東西。
渲染引擎的概述渲染引擎的主要職責是在瀏覽器屏幕上顯示請求的頁面。
渲染引擎可以顯示HTML和XML文檔和圖像。如果您使用額外的插件,引擎還可以顯示不同類型的文檔,如PDF。
渲染引擎與JavaScript引擎類似,不同的瀏覽器也使用不同的渲染引擎。這些是一些流行的:
Gecko - 火狐
WebKit - Safari
Blink - Chrome,Opera(從15版開始)
渲染的過程渲染引擎從網絡層接收所請求文檔的內容。
構建DOM樹
渲染引擎的第一步是解析HTML文檔并將解析的元素轉換為DOM樹中的實際DOM節點。
想象一下你有以下的文字輸入:
Hello, friend!
這個HTML的DOM樹如下所示:
基本上,每個元素都被表示為所有其子元素的父節點子元素直接包含在它的內部。
CSSOM指的是CSS對象模型。當瀏覽器構建頁面的DOM時,它在引用外部theme.css CSS樣式表的head部分遇到link標記。預計它可能需要該資源來呈現頁面,它立即發出請求。假設theme.css文件包含以下內容:
body { font-size: 16px; } p { font-weight: bold; } span { color: red; } p span { display: none; } img { float: right; }
與HTML一樣,引擎需要將CSS轉換為瀏覽器可以使用的東西 - CSSOM。 以下是CSSOM樹的外觀:
你想知道為什么CSSOM有一個樹結構?當計算頁面上任何對象的最后一組樣式時,瀏覽器從適用于該節點的最一般規則開始(例如,如果它是body元素的子元素,則應用所有body樣式),然后遞歸地細化通過應用更具體的規則來計算樣式。
讓我們來看看我們給出的具體例子。包含在body元素中的span標簽中的任何文本的字體大小為16像素,并且具有紅色。這些樣式是從body元素繼承而來的。如果span元素是p元素的子元素,則由于正在應用更具體的樣式,因此不會顯示其內容。
另外請注意,上面的樹不是完整的CSSOM樹,只顯示了我們決定在樣式表中重寫的樣式。每個瀏覽器都提供了一組默認的樣式,也稱為“user agent styles” - 這是我們在沒有明確提供任何樣式時看到的。我們的樣式簡單地覆蓋這些默認值。
構建渲染樹HTML中的可視指令與CSSOM樹中的樣式數據結合在一起用于創建渲染樹。
你可能會問什么是渲染樹?這是按照它們在屏幕上顯示的順序構建的視覺元素樹。它是HTML和相應的CSS的可視化表示。此樹的目的是為了以正確的順序繪制內容。
Webkit中,渲染樹中的每個節點都被稱為的渲染器或渲染對象。
這就是上述DOM和CSSOM樹的渲染器樹的外觀:
為了構建渲染樹,瀏覽器大致如下:
從DOM樹的根開始,它遍歷每個可見節點。某些節點不可見(例如,腳本標記,元標記等),并且由于它們未反映在呈現的輸出中而被忽略。一些節點通過CSS隱藏,并且也從渲染樹中省略。例如,span節點 - 在上面的例子中,它并不存在于渲染樹中,因為我們有一個明確的規則來設置display:none屬性。
對于每個可見節點,瀏覽器找到適當的CSSOM規則并應用它們。
它發出帶有內容及其計算樣式的可見節點
你可以在這里看看RenderObject的源代碼(在WebKit中):https://github.com/WebKit/web...
我們來看看這個類的一些核心內容:
class RenderObject : public CachedImageClient { // Repaint the entire object. Called when, e.g., the color of a border changes, or when a border // style changes. Node* node() const { ... } RenderStyle* style; // the computed style const RenderStyle& style() const; ... }
每個渲染器代表一個矩形區域,通常對應于一個節點的CSS框。它包括幾何信息,例如寬度,高度和位置。
渲染樹的布局當渲染器被創建并添加到樹中時,它沒有位置和大小。計算這些值稱為布局。
HTML使用基于流程的布局模型,這意味著大部分時間內它可以通過一次傳遞計算幾何。坐標系相對于根渲染器。使用頂部和左側坐標。
布局是一個遞歸過程 - 它從根呈現器開始,它對應于HTML文檔的元素。布局通過部分或整個渲染器層次結構遞歸地繼續遞歸,為需要它的每個渲染器計算幾何信息。
根渲染器的位置是0,0,并且其尺寸具有瀏覽器窗口(也稱為視口)的可見部分的尺寸。
開始布局過程意味著給每個節點確切的坐標,它應該出現在屏幕上。
繪制渲染樹在此階段中,遍歷渲染器樹并調用渲染器的paint()方法以在屏幕上顯示內容。
繪畫可以是全局或增量式(與布局類似):
全局 - 整個樹被重新繪制。
增量 - 只有一些渲染器以不影響整個樹的方式進行更改。渲染器使其矩形在屏幕上無效。這會導致操作系統將其視為需要重繪和生成繪畫事件的區域。操作系統通過將幾個區域合并為一個智能方式來完成。
一般來說,了解繪畫是一個漸進的過程是很重要的。為了更好的用戶體驗,渲染引擎會嘗試盡快在屏幕上顯示內容。它不會等到所有的HTML被解析,才開始構建和布置渲染樹。內容的部分內容將被解析并顯示,而該過程繼續保持來自網絡的其余內容項目。
處理腳本和樣式表的順序當解析器到達