摘要:接上一篇瀏覽器渲染的那些事一繼續(xù)說。哈希表的選擇器各不相同,包括,標(biāo)記名稱等。例如,如果選擇器是,就把規(guī)則放入的哈希表中還有一種通用哈希表,適合不屬于上述類別的規(guī)則。
接上一篇瀏覽器渲染的那些事(一)繼續(xù)說。
構(gòu)建呈現(xiàn)樹 Render Tree/Frame Tree 渲染的流程:在這部分我們來講一下構(gòu)建Render Tree的過程。
呈現(xiàn)樹主要是負(fù)責(zé)布局并將自身及其子元素繪制出來。
Webkits RenderObject類是所有呈現(xiàn)器的基類。定義如下:
class RenderObject{ virtual void layout(); virtual void paint(PaintInfo); virtual void rect repeatRect(); Node* node; //DOM node RenderStyle* style; //the computed style RenderLayer* containgLayer; //the }
每個(gè)呈現(xiàn)器都代表了一個(gè)矩形區(qū)域,一般對(duì)應(yīng)于相關(guān)節(jié)點(diǎn)的css框,包含寬度、高度、位置等幾何信息。
不過對(duì)于一些具有復(fù)雜結(jié)構(gòu)的元素,就對(duì)應(yīng)了幾個(gè)可見對(duì)象,這就不是一個(gè)矩形能表現(xiàn)出來的了。例如select元素【對(duì)應(yīng)一個(gè)顯示區(qū)域,一個(gè)下拉列表以及一個(gè)按鈕】。
不規(guī)范的html也會(huì)產(chǎn)生多個(gè)渲染對(duì)象。【css規(guī)范中,一個(gè)行內(nèi)元素只能僅包含行內(nèi)元素或僅包含塊狀元素,在存在混合內(nèi)容時(shí),將會(huì)創(chuàng)建匿名的塊狀渲染對(duì)象包裹住行內(nèi)元素?!?/p>
呈現(xiàn)樹與DOM樹關(guān)系
呈現(xiàn)樹與DOM元素相對(duì)應(yīng),但不是一一對(duì)應(yīng)。
非可視化的DOM元素就不會(huì)插入呈現(xiàn)樹,例如head元素。
display為"none"的元素也不會(huì)顯示在呈現(xiàn)樹中【visibility:hidden的元素仍會(huì)顯示】
除此之外,一些渲染對(duì)象和其對(duì)應(yīng)的DOM節(jié)點(diǎn)不是在樹上的位置也有所不同。
例如浮動(dòng)元素和絕對(duì)定位元素在文本流之外,那么呈現(xiàn)樹會(huì)標(biāo)識(shí)出真實(shí)的結(jié)構(gòu),并用一個(gè)占位結(jié)構(gòu)標(biāo)識(shí)出它們?cè)鹊奈恢谩?/p>
webkit代碼中說明了如何根據(jù)display屬性決定某個(gè)節(jié)點(diǎn)創(chuàng)建什么對(duì)象的渲染對(duì)象。
RenderObject* RenderObject::createObject(Node* node, RenderStyle* style) { Document* doc = node->document(); RenderArena* arena = doc->renderArena(); ... RederObject* o = 0; switch(style->display()){ case NONE: break; case INLINE: o = new (arena) RenderInline(node); break; case BLOCK: o = new (arena) RenderBlock(node); break; ... } return o; }樣式處理
構(gòu)建呈現(xiàn)樹的時(shí)候,需要計(jì)算每一個(gè)呈現(xiàn)對(duì)象的可視化屬性,也就是計(jì)算每個(gè)元素的樣式屬性來完成。這部分比較繁瑣。有的部分是我自己翻譯理解的【如果有誤請(qǐng)指出,謝謝】
樣式計(jì)算的復(fù)雜性
樣式計(jì)算是個(gè)復(fù)雜的工程,首先存儲(chǔ)了無數(shù)的樣式屬性,可能會(huì)造成內(nèi)存問題;如果沒有進(jìn)行優(yōu)化,那么為每個(gè)元素查找匹配的規(guī)則都需要遍歷一遍規(guī)則列表,而且選擇器的結(jié)構(gòu)可能會(huì)造成走錯(cuò)匹配路徑。除此之外,應(yīng)用規(guī)則也有復(fù)雜的層疊規(guī)則。【!important需要?jiǎng)?chuàng)建一個(gè)額外的規(guī)則對(duì)象 CSSImportantRule】
webkit內(nèi)核瀏覽器的處理方案
webkit有樣式對(duì)象,直接把這個(gè)style對(duì)象存在對(duì)應(yīng)的DOM結(jié)點(diǎn)上。因此會(huì)對(duì)匹配的聲明遍歷4次,首先應(yīng)用非重要高優(yōu)先級(jí)的屬性,其次是高優(yōu)先級(jí)重要規(guī)則,然后是普通優(yōu)先級(jí)非重要規(guī)則,最后是普通優(yōu)先級(jí)重要規(guī)則。多次出現(xiàn)的屬性會(huì)根據(jù)正確的層疊順序進(jìn)行解析,最后出現(xiàn)的最終生效。
firefox的處理方案
firefox采用了規(guī)則樹和樣式上下文樹來簡(jiǎn)化樣式計(jì)算。
規(guī)則樹包含了所有已經(jīng)知道規(guī)則匹配的路徑。
在計(jì)算某個(gè)特定元素的樣式上下文時(shí),先計(jì)算規(guī)則樹中的對(duì)應(yīng)路徑,或使用現(xiàn)有路徑,從路徑中最高優(yōu)先級(jí)的底層節(jié)點(diǎn)開始,向上遍歷規(guī)則樹,直到在新的樣式上下文中結(jié)構(gòu)填充完成。也就是css優(yōu)先級(jí)。(在之前寫的css選擇器中有講到。)【規(guī)則樹只有當(dāng)某個(gè)節(jié)點(diǎn)樣式需要計(jì)算時(shí),才會(huì)添加新的計(jì)算路徑。不會(huì)在開始時(shí)候就為所有節(jié)點(diǎn)進(jìn)行計(jì)算】。
如果沒有滿足這個(gè)元素的樣式,對(duì)于inherit的屬性就會(huì)使用initial value【例如"font-size","color"】,對(duì)于reset類型的屬性就使用默認(rèn)值【例如"border","background"】
css rule processor處理方式
css rule processor會(huì)將所有規(guī)則按照級(jí)聯(lián)順序排序,然后放入RuleHash。哈希表的選擇器各不相同,包括ID,class,標(biāo)記名稱等。【例如,如果選擇器是ID,就把規(guī)則放入ID的哈希表中】還有一種通用哈希表,適合不屬于上述類別的規(guī)則。匹配樣式時(shí),就在RuleHash"s table查找,然后合并已經(jīng)保存的樣式列表,然后SelectorMatchesTree 會(huì)去找真正匹配的那個(gè)選擇器。
【查找id和class的速度比屬性選擇器快得多!】
對(duì)于偽元素,是保存在一個(gè)元素hash內(nèi),所以查找偽元素只需要查找一個(gè)哈希表。
有點(diǎn)難理解,看個(gè)栗子【來自MDN】。
//HTML代碼
A few quotes Franklin said that "A penny saved is a penny earned."FDR said "We have nothing tofear but fear itself."
//css樣式如下
/ rule 1 / doc { display: block; text-indent: 1em; }
/* rule 2 */ title { display: block; font-size: 3em; } /* rule 3 */ para { display: block; } /* rule 4 */ [class="emph"] { font-style: italic; }
Rule tree規(guī)則樹如下:
Style context tree樣式上下文樹如下:
4.匹配規(guī)則順序
前面有說到樣式對(duì)象的屬性,如果定義有多個(gè),那么就需要通過層疊順序來決定最終的顯示效果。
層疊順序優(yōu)先級(jí)由高到低:
用戶重要聲明>作者重要聲明>作者普通聲明>用戶普通聲明>瀏覽器聲明
選擇器的優(yōu)先級(jí)呢,可以看我之前寫的css選擇器總結(jié)
規(guī)則排序
匹配段規(guī)則會(huì)根據(jù)級(jí)聯(lián)順序進(jìn)行排序。webkit對(duì)于較小列表使用冒泡排序,對(duì)于較大的列表使用歸并排序。
參考文獻(xiàn):
瀏覽器內(nèi)部工作原理
瀏覽器的渲染原理簡(jiǎn)介
How browsers work
有關(guān)網(wǎng)頁(yè)渲染,每個(gè)前端開發(fā)者都該知道的那點(diǎn)事
前端文摘:深入解析瀏覽器的幕后工作原理
MDN:Style System Overview
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/79536.html
摘要:接上一篇瀏覽器渲染的那些事一繼續(xù)說。哈希表的選擇器各不相同,包括,標(biāo)記名稱等。例如,如果選擇器是,就把規(guī)則放入的哈希表中還有一種通用哈希表,適合不屬于上述類別的規(guī)則。 接上一篇瀏覽器渲染的那些事(一)繼續(xù)說。 構(gòu)建呈現(xiàn)樹 Render Tree/Frame Tree 渲染的流程: 在這部分我們來講一下構(gòu)建Render Tree的過程。呈現(xiàn)樹主要是負(fù)責(zé)布局并將自身及其子元素繪制出來。We...
摘要:接上一篇瀏覽器渲染的那些事一繼續(xù)說。哈希表的選擇器各不相同,包括,標(biāo)記名稱等。例如,如果選擇器是,就把規(guī)則放入的哈希表中還有一種通用哈希表,適合不屬于上述類別的規(guī)則。 接上一篇瀏覽器渲染的那些事(一)繼續(xù)說。 構(gòu)建呈現(xiàn)樹 Render Tree/Frame Tree 渲染的流程: 在這部分我們來講一下構(gòu)建Render Tree的過程。呈現(xiàn)樹主要是負(fù)責(zé)布局并將自身及其子元素繪制出來。We...
摘要:遵循的是異步模塊定義規(guī)范,遵循的是通用模塊定義規(guī)范。不同的腳本加載這個(gè)模塊,得到的都是同一個(gè)實(shí)例。關(guān)于異步那些事就寫到這里了,很多地方理解的不夠深刻希望大家多多指教。 JS異步那些事 一 (基礎(chǔ)知識(shí))JS異步那些事 二 (分布式事件)JS異步那些事 三 (Promise)JS異步那些事 四(HTML 5 Web Workers)JS異步那些事 五 (異步腳本加載) 異步腳本加載 阻塞性...
摘要:需要注意的是,及更早的瀏覽器不支持第一種語(yǔ)法中向延遲函數(shù)傳遞額外參數(shù)的功能。如果在不改變遞歸模式的前提下修善這段代碼解決方案加入定時(shí)器題目四考察和系列解釋立即的對(duì)象,是在本輪事件循環(huán)的結(jié)束時(shí),而不是在下一輪事件循環(huán)的開始時(shí)。 前言:setTimeout是JavaScript中常見的一個(gè)window對(duì)象方法,本文將介紹關(guān)于它的一些基礎(chǔ)知識(shí)和易出錯(cuò)的地方。 1、基礎(chǔ)知識(shí) 作用:setTim...
摘要:原文鏈接瀏覽器渲染那些事之瀏覽器內(nèi)核渲染引擎在各個(gè)瀏覽器廠商你追我趕的形勢(shì)下,截止今日,產(chǎn)生了很多不同的瀏覽器,各個(gè)瀏覽器本質(zhì)大同小異,核心部分基本相似,由渲染引擎和引擎組成。 原文鏈接 瀏覽器渲染那些事之 Reflow、Repaint 瀏覽器內(nèi)核(渲染引擎) 在各個(gè)瀏覽器廠商你追我趕的形勢(shì)下,截止今日,產(chǎn)生了很多不同的瀏覽器,各個(gè)瀏覽器本質(zhì)大同小異,核心部分基本相似,由渲染引擎和 J...
閱讀 1004·2021-11-25 09:43
閱讀 1672·2019-08-30 13:59
閱讀 1589·2019-08-30 11:22
閱讀 2123·2019-08-30 11:06
閱讀 1299·2019-08-28 17:51
閱讀 3717·2019-08-26 12:12
閱讀 778·2019-08-26 12:11
閱讀 443·2019-08-26 12:10