chrome瀏覽器在地址欄輸入U(xiǎn)RL到頁面展示谜疤,這中間發(fā)生了什么佃延?(中)

距上次的導(dǎo)航流程已有些日子,趁著這次休假把剩下的渲染流程也分享出來夷磕。
通過本文可以透視瀏覽器是如何進(jìn)行渲染工作的履肃。

眾所周知,瀏覽器傳輸?shù)南嚓P(guān)文件包括 js文件html文件css文件坐桩。

//HTMl: 超文本 標(biāo)記語言
<p>山野喬治</p>
//CSS:層疊樣式表 
p { color: red }
//JavaScript
p.style.color = 'gray'  通過頁面修改內(nèi)容

1.html的內(nèi)容由標(biāo)記和文本組成尺棋,標(biāo)記也稱為標(biāo)簽。每個(gè)標(biāo)簽都有自己特定的含義绵跷,瀏覽器會(huì)根據(jù)不同的語義化的標(biāo)簽來進(jìn)行渲染不同的內(nèi)容陡鹃。比如上面的的<p>標(biāo)簽會(huì)告訴瀏覽器在這里需要?jiǎng)?chuàng)建一個(gè)新的段落,中間的文本就是段落要顯示的內(nèi)容抖坪。

2.css文件又稱為層疊樣式表萍鲸,是由選擇器和屬性組成。通過css可以改變文字的大小擦俐,顏色等信息脊阴。圖中的p標(biāo)簽,會(huì)把設(shè)定的屬性值蚯瞧,全部應(yīng)用到p標(biāo)簽上嘿期。

3.至于JavaScript,使用這個(gè)可以讓頁面的內(nèi)容‘動(dòng)’起來埋合。也就是大部分的用戶和瀏覽器的交互操作备徐,都是通過JavaScript完成的。


搞清楚了HTML甚颂,CSS蜜猾,JavaScript基本含義之后,我們就開始詳細(xì)了解瀏覽器的渲染機(jī)制吧振诬。

渲染模塊在執(zhí)行過程中會(huì)被劃分為很多子階段蹭睡,輸入的HTML經(jīng)過這些子階段,最后輸出為了像素赶么。我們把這樣的一個(gè)處理流程就叫做渲染流水線肩豁,大致過程如下圖所示。

img

按照渲染的時(shí)間順序,流水線可以分為這幾個(gè)子階段:

  • 構(gòu)建DOM樹
  • 樣式計(jì)算
  • 布局階段
  • 分層
  • 繪制
  • 分塊
  • 光柵化
  • 合成

每個(gè)階段的過程中清钥,我們應(yīng)該重點(diǎn)關(guān)注:1琼锋,開始每個(gè)子階段都有其輸入的內(nèi)容;2祟昭,然后每個(gè)子階段有其處理過程缕坎;3,最終子階段會(huì)生成其輸出內(nèi)容从橘。也就是:輸入-》加工-》輸出

構(gòu)建DOM樹

為什么要構(gòu)建DOM樹呢念赶?

我們?yōu)g覽器是無法直接理解和使用HTML的(HTML標(biāo)記語言是為了讓開發(fā)人員進(jìn)行編程的語言)所以瀏覽器需要將轉(zhuǎn)化為瀏覽器可以理解的結(jié)構(gòu),那就是---DOM樹恰力。

了解過數(shù)據(jù)結(jié)構(gòu)的開發(fā)人員應(yīng)該都清楚什么是樹結(jié)構(gòu)叉谜。有一父節(jié)點(diǎn)可以有很多個(gè)子節(jié)點(diǎn),但一個(gè)子節(jié)點(diǎn)不能被不同的父節(jié)點(diǎn)共享踩萎。在我們?yōu)g覽器的渲染機(jī)制中停局,就頻繁的使用到了樹結(jié)構(gòu)。

那么DOM樹是如何進(jìn)行構(gòu)建并進(jìn)行渲染的呢香府?

DOM樹構(gòu)建過程.png

在構(gòu)建DOM樹的時(shí)候董栽,輸入內(nèi)容就是一個(gè)簡單的HTML文件,然后由HTML解析器進(jìn)行解析企孩,最終輸出一個(gè)樹狀結(jié)構(gòu)的DOM锭碳。

為了能直觀的了解什么是DOM結(jié)構(gòu),可以在控制臺(tái)上輸入document進(jìn)行查看完整的一個(gè)DOM結(jié)構(gòu)勿璃。DOM和HTML內(nèi)容幾乎一摸一樣的擒抛,但是和HTML不同的是,DOM是保存在內(nèi)存中的樹狀結(jié)構(gòu)补疑,可以通過JavaScript來查詢或修改其內(nèi)容歧沪。如何通過JavaScript來修改DOM的內(nèi)容呢?控制臺(tái)輸入以下內(nèi)容

document.getElementsByTagName('p')[0].innerText = 'black'

這個(gè)代碼作用就是把第一個(gè)P標(biāo)簽的文本內(nèi)容轉(zhuǎn)換為black莲组。當(dāng)執(zhí)行這行代碼的時(shí)候诊胞,DOM的一個(gè)p節(jié)點(diǎn)的內(nèi)容成功被修改,同時(shí)頁面的內(nèi)容也會(huì)被修改锹杈。

這就是生成DOM樹的過程撵孤,此刻DOM節(jié)點(diǎn)的樣式我們依然不知道,要讓DOM擁有正確的樣式嬉橙,就需要進(jìn)行下一個(gè)渲染子進(jìn)程了早直。

樣式計(jì)算(Recalculate Style)

樣式計(jì)算的目的是為了計(jì)算DOM節(jié)點(diǎn)中每個(gè)元素的具體樣式,這個(gè)子進(jìn)程大概需要分為三步來完成市框。

1.把CSS轉(zhuǎn)化為瀏覽器能夠理解的結(jié)構(gòu)

那么CSS樣式的來源主要有哪些呢?

  • 通過link引用的外部CSS文件

  • <style>標(biāo)記內(nèi)的CSS

  • 元素的style屬性內(nèi)嵌的CSS

和第一個(gè)構(gòu)建DOM樹一樣糕韧,瀏覽器也是不能直接理解純文本的CSS樣式枫振,所以當(dāng)渲染引擎就收到css文件的時(shí)候喻圃,首先會(huì)進(jìn)行一個(gè)轉(zhuǎn)化操作,將css文本轉(zhuǎn)化為瀏覽器可以理解的結(jié)構(gòu)---styleSheets

同樣粪滤,想要更要直觀的查看styleSheets的結(jié)構(gòu)斧拍,我們可以在控制臺(tái)輸入document.styleSheets,就能看到對應(yīng)的css結(jié)構(gòu)杖小。

styleSheets.png

可以看出肆汹,這個(gè)樣式表包含了很多樣式,已經(jīng)把那三種來源的樣式都包含進(jìn)去了予权。當(dāng)然樣式表的具體結(jié)構(gòu)在這里不贅述昂勉,只介紹渲染引擎會(huì)把獲取到的CSS文件全部轉(zhuǎn)換為styleSheets結(jié)構(gòu)中的數(shù)據(jù),并且該結(jié)構(gòu)同時(shí)具備了查詢和修改功能扫腺,為后面的樣式操作提供了基礎(chǔ)岗照。到此樣式表轉(zhuǎn)化完畢。

2.轉(zhuǎn)換樣式表中的屬性值笆环,使其標(biāo)準(zhǔn)化

我們已經(jīng)把現(xiàn)有的CSS文本轉(zhuǎn)化為了瀏覽器可以理解的結(jié)構(gòu)了攒至,那么接下來就要對其進(jìn)行屬性值的標(biāo)準(zhǔn)化操作。那么什么是屬性值標(biāo)準(zhǔn)化呢躁劣?

body { font-size: 2em }
p { color: blue }
span { display: none }
div { font-weight: bold }
div p { color: green }
div { color: red }

可以看出上述的CSS文本中有很多的屬性值迫吐,如2em,blue账忘,bold志膀。這些類型數(shù)值都不容易被渲染引擎所理解,所以需要將所有值轉(zhuǎn)換為渲染引擎所能理解的標(biāo)準(zhǔn)化的計(jì)算值闪萄,這個(gè)過程就是屬性值標(biāo)準(zhǔn)化梧却。

那么標(biāo)準(zhǔn)化后的屬性值是什么呢?

body { font-size: 32px }
p { color: rgb(0,0,255) }
span { display: none }
div { font-weight: 700 }
div p { color: rgb(0,128,0) }
div { color: rgb(255,0,0) )

3.計(jì)算出DOM樹中的每個(gè)節(jié)點(diǎn)的具體樣式

當(dāng)屬性值已經(jīng)被標(biāo)準(zhǔn)化后败去,接下來我們就要計(jì)算DOM樹中的每個(gè)節(jié)點(diǎn)的樣式屬性了放航,如何計(jì)算呢?

這就涉及到CSS的繼承規(guī)則和層疊規(guī)則了圆裕。

首先是CSS繼承广鳍。CSS繼承就是每個(gè)DOM節(jié)點(diǎn)都包含有父節(jié)點(diǎn)的樣式 這么說可能有點(diǎn)抽象,實(shí)例是如何應(yīng)用的呢吓妆?

body { font-size: 20px }
p {color: blue}
span { display: none }
div { font-weight: bold; color: red }
div p { color: green }

那么如何繼承呢赊时?如下圖所示

css繼承.png

所有的子節(jié)點(diǎn)都繼承了父節(jié)點(diǎn)的樣式。比如body節(jié)點(diǎn)的font-size屬性是20行拢,那么body節(jié)點(diǎn)下面的所有節(jié)點(diǎn)的font-size都等于20祖秒。

樣式計(jì)算過程中第二個(gè)規(guī)則就是樣式層疊。層疊是CSS的一個(gè)基本特征,它是一個(gè)定義了如何合并來自多個(gè)源的屬性值的算法竭缝。它在css中處于核心地位房维,css的全稱是“層疊樣式表”正是強(qiáng)調(diào)了這一點(diǎn)。關(guān)于層疊的具體規(guī)則這里不做介紹抬纸。

總之咙俩,樣式計(jì)算階段的目的救贖為了計(jì)算出DOM節(jié)點(diǎn)中每個(gè)元素的具體樣式,在計(jì)算過程中需要遵守CSS的繼承和層疊兩個(gè)規(guī)則湿故。這個(gè)階段最中輸出的內(nèi)容就是每個(gè)DOM節(jié)點(diǎn)的樣式阿趁,并被保存在ComputerStyle的結(jié)構(gòu)內(nèi)。

如果想要了解每個(gè)DOM元素最終的計(jì)算樣式坛猪,可以打開Chrome的“開發(fā)者工具脖阵,選擇一個(gè)element標(biāo)簽,然后再選擇“Computer”子標(biāo)簽砚哆。

computer中存儲(chǔ)最終計(jì)算的樣式.png

在進(jìn)行計(jì)算之后独撇,我們就進(jìn)行布局階段。

布局階段

我們有DOM樹和DOM樹中元素的樣式之后躁锁,我們還不足以顯示頁面纷铣,因?yàn)檫€不知道DOM元素的幾何位置信息。那么接下來就需要計(jì)算出DOM樹中可見元素的幾何位置战转,我們把這個(gè)計(jì)算過程叫做布局

Chrome在布局階段需要完成兩個(gè)任務(wù):創(chuàng)建布局樹和布局計(jì)算搜立。

1.創(chuàng)建布局樹

你可能注意到了DOM樹還含有很多不可見的元素,比如head標(biāo)簽槐秧,還有使用了display:none屬性的元素啄踊。所以在顯示之前,我們還要額外地構(gòu)建一棵只包含可見元素布局樹刁标。

我們結(jié)合下圖來看看布局樹的構(gòu)造過程:

布局樹構(gòu)造過程.png

從上圖可以看出颠通,DOM樹中所有不可見的節(jié)點(diǎn)都沒有包含到布局樹中。

為了構(gòu)建布局樹膀懈,瀏覽器大體上完成了下面這些工作:

  • 遍歷DOM樹中的所有可見節(jié)點(diǎn)顿锰,并把這些節(jié)點(diǎn)加到布局樹中;
  • 而不可見的節(jié)點(diǎn)會(huì)被布局樹忽略掉启搂,如head標(biāo)簽下面的全部內(nèi)容硼控,再比如body.p.span這個(gè)元素,因?yàn)樗膶傩园琩isplay:none胳赌,所以這個(gè)元素也沒有被包進(jìn)布局樹牢撼。

2.布局計(jì)算

現(xiàn)在我們有了一棵完整的布局樹。那么接下來疑苫,就要計(jì)算布局樹節(jié)點(diǎn)的坐標(biāo)位置了熏版。布局的計(jì)算過程非常復(fù)雜纷责,等到后續(xù)詳解。

在執(zhí)行布局操作的時(shí)候纳决,會(huì)把布局計(jì)算的結(jié)果重新寫會(huì)布局樹中碰逸,所以布局樹既是輸入內(nèi)容也是輸出內(nèi)容乡小,這是布局階段一個(gè)不合理的地方阔加,因?yàn)樵诓季蛛A段并沒有清晰地將輸入內(nèi)容和輸出內(nèi)容區(qū)分開。對于這個(gè)問題满钟,Chrome團(tuán)隊(duì)正在重構(gòu)布局代碼胜榔,下一代布局系統(tǒng)叫做LayoutNG,試圖分離輸入和輸出湃番,從而讓布局算法更加簡單夭织。

綜上本問介紹了渲染進(jìn)程的三個(gè)子進(jìn)程:DOM生成,樣式計(jì)算和布局吠撮。

總結(jié):

  • 瀏覽器不能直接理解HTML文件尊惰,通過轉(zhuǎn)化器將轉(zhuǎn)化為瀏覽器能理解的DOM樹結(jié)構(gòu)。
  • 生成DOM樹之后泥兰,還需要根據(jù)CSS樣式表弄屡,來計(jì)算出DOM樹所有節(jié)點(diǎn)的樣式。
  • 最后計(jì)算DOM元素的布局信息鞋诗,使其保存在布局樹中(輸入DOM樹膀捷,計(jì)算布局信息后,輸出DOM樹)削彬。

子過程比較多全庸,小伙伴迫切叫我健身。渲染進(jìn)程那就先到這里了融痛,剩下的進(jìn)程我們下節(jié)再敘~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末壶笼,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子雁刷,更是在濱河造成了極大的恐慌覆劈,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件安券,死亡現(xiàn)場離奇詭異墩崩,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)侯勉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進(jìn)店門鹦筹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人址貌,你說我怎么就攤上這事铐拐∨羌” “怎么了?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵遍蟋,是天一觀的道長吹害。 經(jīng)常有香客問我,道長虚青,這世上最難降的妖魔是什么它呀? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮棒厘,結(jié)果婚禮上纵穿,老公的妹妹穿的比我還像新娘。我一直安慰自己奢人,他們只是感情好谓媒,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著何乎,像睡著了一般句惯。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上支救,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天抢野,我揣著相機(jī)與錄音,去河邊找鬼搂妻。 笑死蒙保,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的欲主。 我是一名探鬼主播邓厕,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼扁瓢!你這毒婦竟也來了详恼?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤引几,失蹤者是張志新(化名)和其女友劉穎昧互,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體伟桅,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡敞掘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了楣铁。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片玖雁。...
    茶點(diǎn)故事閱讀 40,102評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖盖腕,靈堂內(nèi)的尸體忽然破棺而出赫冬,到底是詐尸還是另有隱情浓镜,我是刑警寧澤,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布劲厌,位于F島的核電站膛薛,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏补鼻。R本人自食惡果不足惜哄啄,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望辽幌。 院中可真熱鬧增淹,春花似錦、人聲如沸乌企。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽加酵。三九已至,卻和暖如春哭当,著一層夾襖步出監(jiān)牢的瞬間猪腕,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工钦勘, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留陋葡,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓彻采,卻偏偏與公主長得像腐缤,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子肛响,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評論 2 355