摘要:渲染樹的布局創建渲染器并將其添加到樹中時,它沒有位置和大小,計算這些值稱為布局。根渲染器的位置為,其尺寸與瀏覽器窗口的可見部分即的大小相同。渲染器使其在屏幕上的矩形無效,這會導致操作系統將其視為需要重新繪制并生成繪事件的區域。
這是專門探索 JavaScript 及其所構建的組件的系列文章的第11篇。
想閱讀更多優質文章請猛戳GitHub博客,一年百來篇優質文章等著你!
如果你錯過了前面的章節,可以在這里找到它們:
JavaScript 是如何工作的:引擎,運行時和調用堆棧的概述!
JavaScript 是如何工作的:深入V8引擎&編寫優化代碼的5個技巧!
JavaScript 是如何工作的:內存管理+如何處理4個常見的內存泄漏 !
JavaScript 是如何工作的:事件循環和異步編程的崛起+ 5種使用 async/await 更好地編碼方式!
JavaScript 是如何工作的:深入探索 websocket 和HTTP/2與SSE +如何選擇正確的路徑!
JavaScript 是如何工作的:與 WebAssembly比較 及其使用場景 !
JavaScript 是如何工作的:Web Workers的構建塊+ 5個使用他們的場景!
JavaScript 是如何工作的:Service Worker 的生命周期及使用場景!
JavaScript 是如何工作的:Web 推送通知的機制!
JavaScript是如何工作的:使用 MutationObserver 跟蹤 DOM 的變化
當你構建 Web 應用程序時,你不只是編寫多帶帶運行的 JavaScript 代碼,你編寫的 JavaScript 正在與環境進行交互。了解這種環境,它的工作原理以及它的組,這些有助于你夠構建更好的應用程序,并為應用程序發布后可能出現的潛在問題做好充分準備。
瀏覽器的主要組件包括:
用戶界面 (User interface): 包括地址欄、后退/前進按鈕、書簽目錄等,也就是你所看到的除了用來顯示你所請求頁面的主窗口之外的其他部分
瀏覽器引擎 (Browser engine):用來查詢及操作渲染引擎的接口
渲染引擎 (Rendering engine):用來顯示請求的內容,例如,如果請求內容為 html,它負責解析 html 及 css,并將解析后的結果顯示出來
網絡 (Networking):用來完成網絡調用,例如http請求,它具有平臺無關的接口,可以在不同平臺上工作
UI 后端 (UI backend):用來繪制類似組合選擇框及對話框等基本組件,具有不特定于某個平臺的通用接口,底層使用操作系統的用戶接口
JS 解釋器 (JavaScript engine):用來解釋執行JS代碼
數據存儲 (Data persistence): 屬于持久層,瀏覽器需要在硬盤中保存類似 cookie 的各種數據,HTML5定義了 Web Database 技術,這是一種輕量級完整的客戶端存儲技術,支持的存儲機制類型包括 localStorage、indexDB、WebSQL和 FileSystem。
在這篇文章中,將重點討論渲染引擎,因為它處理 HTML 和 CSS 的解析和可視化,這是大多數 JavaScript 應用程序經常與之交互的東西。
渲染引擎概述渲染引擎的職責就是渲染,即在瀏覽器窗口中顯示所請求的內容。
渲染引擎可以顯示 HTML 和 XML 文檔和圖像。如果使用其他插件,渲染引擎還可以顯示不同類型的文檔,如 PDF。
渲染引擎 (Rendering engines)與 JavaScript 引擎類似,不同的瀏覽器也使用不同的渲染引擎。以下是一些最受歡迎的:
Gecko?—?Firefox
WebKit?—?Safari
Blink?—?Chrome,Opera (版本 15 之后)
Firefox、Chrome 和 Safari 是基于兩種渲染引擎構建的,Firefox 使用 Geoko——Mozilla 自主研發的渲染引擎,Safari 和 Chrome 都使用 Webkit。Blink 是 Chrome 基于 WebKit的自主渲染引擎。
渲染的過程渲染引擎從網絡層接收所請求文檔的內容。
解析 HTML 以構建 Dom 樹 -> 構建 Render 樹 -> 布局 Render 樹 -> 繪制 Render 樹
構建 Dom 樹渲染現引擎的第一步是解析 HTML文檔,并將解析后的元素轉換為 DOM 樹中的實際 DOM 節點。
假如有如下 Html 結構
Hello, friend!
對應的 DOM 樹如下:
基本上,每個元素都表示為所有元素的父節點,這些元素直接包含在元素中。
構建 CSSOMCSSOM 指的是 CSS 對象模型。 當瀏覽器構建頁面的 DOM 時,它在 head 標簽下如遇到了一個 link 標記且引用了外部 theme.css CSS 樣式表。 瀏覽器預計可能需要該資源來呈現頁面,它會立即發送請求。 假設 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 元素的子元素,那么它的內容就不會被顯示,因為它被應用了更具體的樣式(display: none)。
另請注意,上面的樹不是完整的 CSSOM 樹,只顯示我們決定在樣式表中覆蓋的樣式。 每個瀏覽器都提供一組默認樣式,也稱為“user agent stylesheet”。這是我們在未明確指定任何樣式時看到的樣式,我們的樣式會覆蓋這些默認值。
不同瀏覽器對于相同元素的默認樣式并不一致,這也是為什么我們在 CSS 的最開始要寫 *{padding:0;marging:0};,也就是我們要重置CSS默認樣式的。
構建渲染樹CSSOM 樹和 DOM 樹連接在一起形成一個 render tree,渲染樹用來計算可見元素的布局并且作為將像素渲染到屏幕上的過程的輸入。
DOM 樹和 CSSOM 樹連接在一起形成 render tree .
render tree 只包含了用于渲染頁面的節點
布局計算了每一個對象的準確的位置以及大小
繪畫是最后一步,繪畫要求利用 render tree 來將像素顯示到屏幕上
渲染樹中的每個節點在 Webkit 中稱為渲染器或渲染對象。
收下是上面 DOM 和 CSSOM 樹的渲染器樹的樣子:
為了構建渲染樹,瀏覽器大致執行以下操作:
從 DOM 樹根節點開始,遍歷每一個可見的節點
一些節點是完全不可見的(比如 script標簽,meta標簽等),這些節點會被忽略,因為他們不會影響渲染的輸出
一些節點是通過 CSS 樣式隱藏了,這些節點同樣被忽略——例如上例中的 span 節點在 render tree 中被忽略,因為 span 樣式是 display:none
對每一個可見的節點,找到合適的匹配的CSSOM規則,并且應用樣式
顯示可見節點(節點包括內容和被計算的樣式)
“visibility:hidden” 和 “display:none” 之間的不同,“visibility:hidden” 將元素設置為不可見,但是同樣在布局上占領一定空間(例如,它會被渲染成為空盒子),但是 “display:none” 的元素是將節點從整個 render tree 中移除,所以不是布局中的一部分 。
你可以在這里查看 RenderObject 的源代碼(在 WebKit 中):
https://github.com/WebKit/web...
我們來看看這個類的一些核心內容:
每個渲染器代表一個矩形區域,通常對應于一個節點的 CSS 盒模型。它包含幾何信息,例如寬度、高度和位置。
渲染樹的布局創建渲染器并將其添加到樹中時,它沒有位置和大小,計算這些值稱為布局。
HTML使用基于流的布局模型,這意味著大多數時間它可以一次性計算幾何圖形。坐標系統相對于根渲染器,使用左上原點坐標。
布局是一個遞歸過程 - 它從根渲染器開始,它對應于 HTML 文檔的 元素。 布局以遞歸方式繼續通過部件或整個渲染器層次結構,為每個需要它的渲染器計算幾何信息。
根渲染器的位置為0,0,其尺寸與瀏覽器窗口的可見部分(即viewport)的大小相同。開始布局過程意味著給每個節點在屏幕上應該出現的確切坐標。
繪制渲染樹在此繪制,遍歷渲染器樹并調用渲染器的 paint() 方法以在屏幕上顯示內容。
繪圖可以是全局的或增量式的(與布局類似):
全局 — 整棵樹被重繪
增量式 — 只有一些渲染器以不影響整個樹的方式改變。 渲染器使其在屏幕上的矩形無效,這會導致操作系統將其視為需要重新繪制并生成繪 paint 事件的區域。 操作系統通過將多個區域合并為一個來智能完成。
總的來說,重要的中要理解繪圖是一個漸進的過程。為了更好的用戶體驗,渲染引擎將盡可能快地在屏幕上顯示內容。它不會等到解析完所有 HTML 后才開始構建和布局渲染樹,而是解析和顯示部分內容,同時繼續處理來自網絡的其余內容項。
處理腳本和樣式表的順序當解析器到達 標記時,將立即解析并執行腳本。文檔的解析將暫停,直到執行腳本為止。這意味著這個過程是同步的。
如果腳本是外部的,那么首先必須從網絡中獲取它(也是同步的)。所有解析都停止,直到獲取完成。HTML5 新加了async 或 defer 屬性,將腳本標記為異步的,以便由不同的線程解析和執行。
優化渲染性能如果你想優化自己的應用,則需要關注五個主要方面,這些是你自己可以控制的:
JavaScript? ?— 在之前的文章中,討論了如果編寫優化代碼的主題抱包括如果編寫代碼才不會阻止UI,和提高內存利用等等。在渲染時,需要考慮 JavaScript 代碼與頁面 上DOM 素交互的方式。 JavaScript 可以在 UI中創建大量更改,尤其是在 SPA 中。
樣式計算 — 這是根據匹配選擇器確定哪個 CSS 規則適用于哪個元素的過程。 定義規則后,將應用它們并計算每個元素的最終樣式。
布局 — 一旦瀏覽器知道哪些規則適用于某個元素,它就可以開始計算后者占用多少空間以及它在瀏覽器屏幕上的位置。Web 的布局模型定義了一個元素可以影響其他元素。例如,
的寬度會影響其子元素的寬度,等等。這意味著布局過程是計算密集型的,該繪圖是在多個圖層完成的。繪圖 —— 這是實際像素被填充的地方,這個過程包括繪制文本、顏色、圖像、邊框、陰影等——每個元素的每個可視部分。
合成 ?— 由于頁面部分可能被繪制成多個層,因此它們需要以正確的順序繪制到屏幕上,以便頁面渲染正確。這是非常重要的,特別是對于重疊的元素。
優化你的 JavaScriptJavaScript 經常觸發瀏覽器中的視覺變化,構建 SPA 時更是如此。
以下是一些優化 JavaScript 渲染技巧:
避免使用 setTimeout 或 setInterval 進行可視更新。 這些將在幀中的某個點調用 callback ,可能在最后。我們想要做的是在幀開始時觸發視覺變化而不是錯過它。
如 之前文章 所述,將長時間運行的 JavaScript 計算轉移到 Web Workers。
使用微任務在多個幀中變更 DOM。這是在任務需要訪問 DOM 時使用的, Web Worker 無法訪問 DOM。這基本上意味著你要把一個大任務分解成更小的任務,然后根據任務的性質在 requestAnimationFrame, setTimeout, setInterval 中運行它們。
優化你的 CSS通過添加和刪除元素,更改屬性等來修改 DOM 將使瀏覽器重新計算元素樣式,并且在許多情況下,重新計算整個頁面的布局或至少部分布局。
要優化渲染,考慮以下事項:
減少選擇器的復雜性,與構造樣式本身的其他工作相比,選擇器復雜性可以占用計算元素樣式所需時間的50%以上。
* 減少必須進行樣式計算的元素的數量。本質上,直接對一些元素進行樣式更改,而不是使整個頁面無效。
優化布局瀏覽器的布局重新計算可能非常繁重。 考慮以下優化:
盡可能減少布局的數量。當你更改樣式時,瀏覽器會檢查是否有任何更改需要重新計算布局。對寬度、高度、左、頂等屬性的更改,以及通常與幾何相關的屬性的更改,都需要布局。所以,盡量避免改變它們。
盡量使用 flexbox 而不是老的布局模型。它運行速度更快,可為你的應用程序創造巨大的性能優勢。
避免強制同步布局。需要記住的是,在 JavaScript 運行時,前一幀中的所有舊布局值都是已知的,可以查詢。如果你訪問 box.offsetHeight,那就不成問題了。但是,如果你在訪問 box 之前更改了它的樣式(例如,通過動態地向元素添加一些 CSS 類),瀏覽器必須先應用樣式更改并執行布局過程,這是非常耗時和耗費資源的,所以盡可能避免。
優化繪圖這通常是所有任務中運行時間最長的,因此盡可能避免這種情況非常重要。 以下是我們可以做的事情:
除了變換(transform)和透明度之外,改變其他任何屬性都會觸發重新繪圖,請謹慎使用。
如果觸發了布局,那也會觸發繪圖,因為更改布局會導致元素的視覺效果也改變。
通過圖層提升和動畫編排來減少重繪區域。
原文:
https://blog.sessionstack.com...
代碼部署后可能存在的BUG沒法實時知道,事后為了解決這些BUG,花了大量的時間進行log 調試,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug。
你的點贊是我持續分享好東西的動力,歡迎點贊!
交流干貨系列文章匯總如下,覺得不錯點個Star,歡迎 加群 互相學習。
https://github.com/qq44924588...
我是小智,公眾號「大遷世界」作者,對前端技術保持學習愛好者。我會經常分享自己所學所看的干貨,在進階的路上,共勉!
關注公眾號,后臺回復福利,即可看到福利,你懂的。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/100967.html
摘要:渲染引擎的概述渲染引擎的主要職責是在瀏覽器屏幕上顯示請求的頁面。中,渲染樹中的每個節點都被稱為的渲染器或渲染對象。坐標系相對于根渲染器。增量只有一些渲染器以不影響整個樹的方式進行更改。渲染器使其矩形在屏幕上無效。 到目前為止,在我們之前的JavaScript工作原理系列文章中,我們一直關注JavaScript作為一種語言,其功能,它如何在瀏覽器中執行,如何優化等等。 但是,當您構建We...
摘要:在中渲染樹中的每個節點即是一個渲染器或者渲染器對象。計算的樣式每個渲染器對象代表一個矩形區域通常是和一個節點的盒模型相對應。坐標系統是相對于根渲染器的。根渲染器的定位為和大小即為瀏覽器窗口的可視化部分比如。渲染器作廢其在屏幕上的矩形區域。 原文請查閱這里,略有刪減,本文采用知識共享署名 4.0 國際許可協議共享,BY Troland。 本系列持續更新中,Github 地址請查閱這里。 ...
摘要:在中渲染樹中的每個節點即是一個渲染器或者渲染器對象。計算的樣式每個渲染器對象代表一個矩形區域通常是和一個節點的盒模型相對應。坐標系統是相對于根渲染器的。根渲染器的定位為和大小即為瀏覽器窗口的可視化部分比如。渲染器作廢其在屏幕上的矩形區域。 原文請查閱這里,略有刪減,本文采用知識共享署名 4.0 國際許可協議共享,BY Troland。 本系列持續更新中,Github 地址請查閱這里。 ...
摘要:在中渲染樹中的每個節點即是一個渲染器或者渲染器對象。計算的樣式每個渲染器對象代表一個矩形區域通常是和一個節點的盒模型相對應。坐標系統是相對于根渲染器的。根渲染器的定位為和大小即為瀏覽器窗口的可視化部分比如。渲染器作廢其在屏幕上的矩形區域。 原文請查閱這里,略有刪減,本文采用知識共享署名 4.0 國際許可協議共享,BY Troland。 本系列持續更新中,Github 地址請查閱這里。 ...
摘要:為了方便大家共同學習,整理了之前博客系列的文章,目前已整理是如何工作這個系列,可以請猛戳博客查看。以下列出該系列目錄,歡迎點個星星,我將更友動力整理理優質的文章,一起學習。 為了方便大家共同學習,整理了之前博客系列的文章,目前已整理 JavaScript 是如何工作這個系列,可以請猛戳GitHub博客查看。 以下列出該系列目錄,歡迎點個星星,我將更友動力整理理優質的文章,一起學習。 J...
閱讀 2627·2021-11-23 09:51
閱讀 861·2021-09-24 10:37
閱讀 3612·2021-09-02 15:15
閱讀 1962·2019-08-30 13:03
閱讀 1881·2019-08-29 15:41
閱讀 2624·2019-08-29 14:12
閱讀 1424·2019-08-29 11:19
閱讀 3301·2019-08-26 13:39