成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

JavaScript 工作原理之十一-渲染引擎及性能優(yōu)化小技巧

Allen / 3511人閱讀

摘要:在中渲染樹(shù)中的每個(gè)節(jié)點(diǎn)即是一個(gè)渲染器或者渲染器對(duì)象。計(jì)算的樣式每個(gè)渲染器對(duì)象代表一個(gè)矩形區(qū)域通常是和一個(gè)節(jié)點(diǎn)的盒模型相對(duì)應(yīng)。坐標(biāo)系統(tǒng)是相對(duì)于根渲染器的。根渲染器的定位為和大小即為瀏覽器窗口的可視化部分比如。渲染器作廢其在屏幕上的矩形區(qū)域。

原文請(qǐng)查閱這里,略有刪減,本文采用知識(shí)共享署名 4.0 國(guó)際許可協(xié)議共享,BY Troland。

本系列持續(xù)更新中,Github 地址請(qǐng)查閱這里。

這是 JavaScript 工作原理的第十一章。

迄今為止,之前的 JavaScript 工作原理系列文章集中于關(guān)注 JavaScript 語(yǔ)言本身的功能,在瀏覽器中的執(zhí)行情況,如何優(yōu)化等等。

然而,當(dāng)在構(gòu)建網(wǎng)絡(luò)應(yīng)用的時(shí)候,不僅僅只是編寫(xiě)自己運(yùn)行的 JavaScript 代碼。所編寫(xiě)的 JavaScript 代碼與運(yùn)行環(huán)境息息相關(guān)。理解 JavaScript 運(yùn)行環(huán)境,它的運(yùn)行原理以及其組成會(huì)讓你構(gòu)建出更好的應(yīng)用并且一旦讓?xiě)?yīng)用程序運(yùn)行于各種環(huán)境下的時(shí)候,讓你更加胸有成竹地應(yīng)對(duì)潛在的問(wèn)題。

那么,讓我們一探瀏覽器主要組件吧:

用戶(hù)界面: 包括地址欄,后退和前進(jìn)按鈕,書(shū)簽菜單等等。本質(zhì)上,這里包含了除顯示用戶(hù)所看到的網(wǎng)頁(yè)本身的窗口以外的瀏覽器的每個(gè)部分。

瀏覽器引擎: 處理用戶(hù)界面和渲染引擎的交互

渲染引擎: 負(fù)責(zé)顯示網(wǎng)頁(yè)。渲染引擎解析 HTML 和 CSS 并在屏幕上顯示解析的內(nèi)容。

網(wǎng)絡(luò): 使用各個(gè)平臺(tái)的不同實(shí)現(xiàn)所發(fā)起的諸如 XHR 請(qǐng)求的網(wǎng)絡(luò)調(diào)用,這些網(wǎng)絡(luò)調(diào)用是基于跨平臺(tái)的接口實(shí)現(xiàn)的。

UI 后端: 負(fù)責(zé)繪制諸如復(fù)選框和窗口的核心部件。它暴露出一個(gè)平臺(tái)無(wú)關(guān)的泛型接口。它底層使用操作系統(tǒng) UI 方法。

JavaScript 引擎: 我們?cè)谥暗南盗形恼轮杏性敿?xì)介紹過(guò)。基本上,這是 JavaScript 代碼執(zhí)行的地方。

數(shù)據(jù)存儲(chǔ): 網(wǎng)絡(luò)應(yīng)用可能需要本地存儲(chǔ)所有數(shù)據(jù)。支持的存儲(chǔ)機(jī)制類(lèi)型包括 localStorage, indexDB, WebSQL 以及 FileSystem。

本文將專(zhuān)注介紹渲染引擎,因?yàn)樗怯脕?lái)處理 HTML 和 CSS 的解析和可視化的,而這些是大多數(shù)的 JavaScript 應(yīng)用需要持續(xù)進(jìn)行交互的方面。

渲染引擎概述

渲染引擎的主要職責(zé)即在瀏覽器屏幕上顯示請(qǐng)求的頁(yè)面。

渲染引擎可以顯示 HTML,XML 文檔以及圖片。如果使用額外的插件,就可以顯示諸如 PDF 的不同類(lèi)型的文檔。

渲染引擎

與 JavaScript 引擎類(lèi)似,不同瀏覽器也使用不同的渲染引擎。以下為比較流行的引擎:

Gecko-Firefox

WebKit-Safari

Blink-Chrome, Opera(從版本 15 開(kāi)始)

渲染過(guò)程

渲染引擎從網(wǎng)絡(luò)層獲取到請(qǐng)求的文檔內(nèi)容。

構(gòu)建 DOM 樹(shù)

渲染引擎的第一步即解析 HTML 文檔和轉(zhuǎn)化解析的元素為 DOM 樹(shù) 上的實(shí)際 DOM 節(jié)點(diǎn)。

假設(shè)有如下的文本輸入框:


  
    
    
  
  
    

Hello, friend!

Smiley face

HTML 的 DOM 樹(shù)類(lèi)似這樣:

基本上,每個(gè)元素是直接包含于其內(nèi)的元素的父節(jié)點(diǎn)。然后依次類(lèi)推。

構(gòu)建 CSSOM 樹(shù)

CSSOM 即 CSS Object Model。當(dāng)瀏覽器構(gòu)建頁(yè)面的 DOM 樹(shù)的時(shí)候,它在 head 標(biāo)簽部分遇到一個(gè)引用外部 theme.css 樣式表的 link 標(biāo)簽。表示它可能需要樣式表來(lái)渲染頁(yè)面,于是便馬上分派一個(gè)請(qǐng)求來(lái)獲取樣式表。假設(shè)以下為 theme.css 文件內(nèi)容:

body { 
  font-size: 16px;
}

p { 
  font-weight: bold; 
}

span { 
  color: red; 
}

p span { 
  display: none; 
}

img { 
  float: right; 
}

與 HTML 一樣,渲染引擎需要把 CSS 轉(zhuǎn)化為瀏覽器可以操作的東西-即 CSSOM。以下為 CSSOM 的大概模樣:

想知道為什么 CSSOM 是樹(shù)狀結(jié)構(gòu)的嗎?當(dāng)為頁(yè)面上的任意對(duì)象計(jì)算其最終的樣式集的時(shí)候,瀏覽器先把最為通用的樣式規(guī)則應(yīng)用于該節(jié)點(diǎn)(比如,它是 body 的子節(jié)點(diǎn),會(huì)先應(yīng)用 body 的所有樣式)然后通過(guò)應(yīng)用更為具體的樣式規(guī)則來(lái)遞歸重定義計(jì)算的樣式。

讓我們看下具體的例子吧。body 中的 span 標(biāo)簽中的任何文字樣式為字體大小 16 像素且字體顏色為紅色。這些樣式繼承自 body 元素。p 元素的子元素 span 由于應(yīng)用了更為具體的樣式從而不會(huì)顯示其內(nèi)容(display:none)。

還有,請(qǐng)注意以上 CSSOM 樹(shù)并不完整而且只顯示了樣式表中指定的重寫(xiě)樣式。每個(gè)瀏覽器提供了一份默認(rèn)的樣式集即 『用戶(hù)代理樣式』- 這即當(dāng)沒(méi)有提供任何樣式的時(shí)候的默認(rèn)顯示樣式。我們的樣式只是簡(jiǎn)單地重寫(xiě)了這些默認(rèn)樣式。

構(gòu)建渲染樹(shù)

HTML 中的可視化指令和 CSSOM 樹(shù)的樣式數(shù)據(jù)結(jié)合起來(lái)創(chuàng)建渲染樹(shù)。

你可能為問(wèn)渲染樹(shù)是什么?它是按順序構(gòu)建可視化元素并顯示在屏幕上的樹(shù)。它是帶有相應(yīng)的樣式的 HTML 的視覺(jué)表現(xiàn)。該樹(shù)旨在按正確的順序繪制內(nèi)容。

在 Webkit 中渲染樹(shù)中的每個(gè)節(jié)點(diǎn)即是一個(gè)渲染器或者渲染器對(duì)象。

以下為以上的 DOM 和 CSSOM 樹(shù)合成的渲染器樹(shù)的大概模樣:

為了創(chuàng)建渲染樹(shù),瀏覽器大概做了幾下幾件事:

從 DOM 樹(shù)的根節(jié)點(diǎn)開(kāi)始,遍歷每個(gè)可見(jiàn)節(jié)點(diǎn)。一些節(jié)點(diǎn)是不可見(jiàn)的(比如,script 標(biāo)簽,meta 標(biāo)簽等等),然后會(huì)被忽略,因?yàn)樗鼈儾⒉粫?huì)在渲染的輸出中顯示。一些節(jié)點(diǎn)通過(guò)樣式隱藏然后也會(huì)被忽略。比如以上例子中的 span 節(jié)點(diǎn),因?yàn)闉槠滹@式設(shè)置了 display: none 的樣式。

瀏覽器為每個(gè)可見(jiàn)節(jié)點(diǎn)應(yīng)用相對(duì)應(yīng)的 CSSOM 規(guī)則并應(yīng)用這些樣式規(guī)則。

釋放出包含內(nèi)容及其經(jīng)過(guò)計(jì)算的樣式的可見(jiàn)節(jié)點(diǎn)。

可以瀏覽下 RenderObject 的源碼(Webkit 中):https://github.com/WebKit/web...

看一下這個(gè)類(lèi)的一些核心構(gòu)件吧:

class RenderObject : public CachedImageClient {
  // 重繪整個(gè)對(duì)象。當(dāng)邊框顏色改變或者邊框樣式更改的時(shí)候調(diào)用。
  
  Node* node() const { ... }
  
  RenderStyle* style;  // 計(jì)算的樣式
  const RenderStyle& style() const;
  
  ...
}

每個(gè)渲染器對(duì)象代表一個(gè)矩形區(qū)域通常是和一個(gè)節(jié)點(diǎn)的 CSS 盒模型相對(duì)應(yīng)。它包括諸如寬度,高度以及定位的幾何信息。

渲染樹(shù)布局

當(dāng)創(chuàng)建了渲染器并且添加到渲染樹(shù)的時(shí)候,它并沒(méi)有定位和大小的信息。計(jì)算這些值即稱(chēng)為布局。

HTML 使用了流式布局模型,意即大多數(shù)情況下可以一次性計(jì)算出渲染器的幾何信息。坐標(biāo)系統(tǒng)是相對(duì)于根渲染器的。這里使用 Top 和 left 坐標(biāo)。

布局是一個(gè)遞歸的過(guò)程-它從根渲染器開(kāi)始進(jìn)行渲染,根渲染器即 HTML 文檔的 html 元素。布局繼續(xù)通過(guò)一部分或者整個(gè)渲染器層級(jí)結(jié)構(gòu)遞歸進(jìn)行,為每個(gè)需要計(jì)算幾何信息的渲染器計(jì)算其信息。

根渲染器的定位為 0,0 和大小即為瀏覽器窗口的可視化部分(比如 viewport)。

進(jìn)行布局的過(guò)程即計(jì)算出每個(gè)節(jié)點(diǎn)在屏幕上顯示的準(zhǔn)確位置。

繪制渲染樹(shù)

該階段,遍歷渲染器樹(shù)然后調(diào)用渲染器的 paint() 方法來(lái)在屏幕上顯示其內(nèi)容。

繪制可以是全局或增量式的(類(lèi)似于布局):

全局-重繪整個(gè)樹(shù)。

增量-以某種方式只更改部分渲染器而不會(huì)影響到整顆樹(shù)。渲染器作廢其在屏幕上的矩形區(qū)域。這會(huì)導(dǎo)致操作系統(tǒng)把它看成是一個(gè)需要重繪的區(qū)域并生成一個(gè) paint 事件。操作系統(tǒng)會(huì)智能地把幾個(gè)區(qū)域合并成一個(gè)以提升渲染性能。

總之,理解繪制是個(gè)漸進(jìn)式的過(guò)程是很重要的。為了更好的交互體驗(yàn),渲染引擎會(huì)試圖盡快在屏幕上顯示內(nèi)容。它不會(huì)等待所有的 HTML 結(jié)構(gòu)解析完成才開(kāi)始構(gòu)建和布局渲染樹(shù)。會(huì)優(yōu)先解析和顯示部分內(nèi)容,與此同時(shí)持續(xù)處理從網(wǎng)絡(luò)接收的剩下的內(nèi)容項(xiàng)。

腳本和樣式的處理順序

當(dāng)解析器遇到

閱讀需要支付1元查看
<