摘要:部分讀者向我反饋對(duì)于最后的瀏覽器渲染布局這塊不是很清晰,所以本文就瀏覽器渲染流程多帶帶開篇講解,希望大家都能有新的收獲。瀏覽器主要組件結(jié)構(gòu)瀏覽器主要組件渲染引擎和使用自主研發(fā)的渲染引擎。所以瀏覽器的渲染過程主要包括以下幾步解析生成樹。
在之前寫過的一篇《"天龍八步"細(xì)說瀏覽器輸入U(xiǎn)RL后發(fā)生了什么》一文中,和大家分享了從在瀏覽器中輸入網(wǎng)址URL到最終頁面展示的整個(gè)過程。部分讀者向我反饋對(duì)于最后的瀏覽器渲染布局這塊不是很清晰,所以本文就瀏覽器渲染流程多帶帶開篇講解,希望大家都能有新的收獲。
瀏覽器主要組件結(jié)構(gòu)
(瀏覽器主要組件)
渲染引擎——webkit和Gecko
Firefox使用Geoko——Mozilla自主研發(fā)的渲染引擎。
Safari和Chrome都使用webkit。Webkit是一款開源渲染引擎,它本來是為linux平臺(tái)研發(fā)的,后來由Apple移植到Mac及Windows上。
本文我主要以webkit渲染引擎來講解,盡管webkit和Gecko使用的術(shù)語稍有不同,他們的主要流程基本相同。
(webkit渲染引擎流程)
關(guān)鍵渲染路徑
關(guān)鍵渲染路徑是指瀏覽器從最初接收請(qǐng)求來的HTML、CSS、javascript等資源,然后解析、構(gòu)建樹、渲染布局、繪制,最后呈現(xiàn)給客戶能看到的界面這整個(gè)過程。
所以瀏覽器的渲染過程主要包括以下幾步:
解析HTML生成DOM樹。
解析CSS生成CSSOM規(guī)則樹。
將DOM樹與CSSOM規(guī)則樹合并在一起生成渲染樹。
遍歷渲染樹開始布局,計(jì)算每個(gè)節(jié)點(diǎn)的位置大小信息。
將渲染樹每個(gè)節(jié)點(diǎn)繪制到屏幕。
構(gòu)建DOM樹
當(dāng)瀏覽器接收到服務(wù)器響應(yīng)來的HTML文檔后,會(huì)遍歷文檔節(jié)點(diǎn),生成DOM樹。
需要注意的是,DOM樹的生成過程中可能會(huì)被CSS和JS的加載執(zhí)行阻塞。渲染阻塞問題下文會(huì)講。
構(gòu)建CSSOM規(guī)則樹
瀏覽器解析CSS文件并生成CSS規(guī)則樹,每個(gè)CSS文件都被分析成一個(gè)StyleSheet對(duì)象,每個(gè)對(duì)象都包含CSS規(guī)則。CSS規(guī)則對(duì)象包含對(duì)應(yīng)于CSS語法的選擇器和聲明對(duì)象以及其他對(duì)象。
渲染阻塞
當(dāng)瀏覽器遇到一個(gè) script 標(biāo)記時(shí),DOM 構(gòu)建將暫停,直至腳本完成執(zhí)行,然后繼續(xù)構(gòu)建DOM。每次去執(zhí)行JavaScript腳本都會(huì)嚴(yán)重地阻塞DOM樹的構(gòu)建,如果JavaScript腳本還操作了CSSOM,而正好這個(gè)CSSOM還沒有下載和構(gòu)建,瀏覽器甚至?xí)舆t腳本執(zhí)行和構(gòu)建DOM,直至完成其CSSOM的下載和構(gòu)建。
所以,script 標(biāo)簽的位置很重要。實(shí)際使用時(shí),可以遵循下面兩個(gè)原則:
CSS 優(yōu)先:引入順序上,CSS 資源先于 JavaScript 資源。
JS置后:我們通常把JS代碼放到頁面底部,且JavaScript 應(yīng)盡量少影響 DOM 的構(gòu)建。
當(dāng)解析html的時(shí)候,會(huì)把新來的元素插入dom樹里面,同時(shí)去查找css,然后把對(duì)應(yīng)的樣式規(guī)則應(yīng)用到元素上,查找樣式表是按照從右到左的順序去匹配的。
例如: div p {font-size: 16px},會(huì)先尋找所有p標(biāo)簽并判斷它的父標(biāo)簽是否為div之后才會(huì)決定要不要采用這個(gè)樣式進(jìn)行渲染)。
所以,我們平時(shí)寫CSS時(shí),盡量用id和class,千萬不要過渡層疊。
構(gòu)建渲染樹
通過DOM樹和CSS規(guī)則樹我們便可以構(gòu)建渲染樹。瀏覽器會(huì)先從DOM樹的根節(jié)點(diǎn)開始遍歷每個(gè)可見節(jié)點(diǎn)。對(duì)每個(gè)可見節(jié)點(diǎn),找到其適配的CSS樣式規(guī)則并應(yīng)用。
渲染樹構(gòu)建完成后,每個(gè)節(jié)點(diǎn)都是可見節(jié)點(diǎn)并且都含有其內(nèi)容和對(duì)應(yīng)規(guī)則的樣式。這也是渲染樹與DOM樹的最大區(qū)別所在。渲染樹是用于顯示,那些不可見的元素當(dāng)然就不會(huì)在這棵樹中出現(xiàn)了,譬如。除此之外,display等于none的也不會(huì)被顯示在這棵樹里頭,但是visibility等于hidden的元素是會(huì)顯示在這棵樹里頭的。
渲染樹布局
布局階段會(huì)從渲染樹的根節(jié)點(diǎn)開始遍歷,然后確定每個(gè)節(jié)點(diǎn)對(duì)象在頁面上的確切大小與位置,布局階段的輸出是一個(gè)盒子模型,它會(huì)精確地捕獲每個(gè)元素在屏幕內(nèi)的確切位置與大小。
渲染樹繪制
在繪制階段,遍歷渲染樹,調(diào)用渲染器的paint()方法在屏幕上顯示其內(nèi)容。渲染樹的繪制工作是由瀏覽器的UI后端組件完成的。
reflow與repaint:
根據(jù)渲染樹布局,計(jì)算CSS樣式,即每個(gè)節(jié)點(diǎn)在頁面中的大小和位置等幾何信息。HTML默認(rèn)是流式布局的,CSS和js會(huì)打破這種布局,改變DOM的外觀樣式以及大小和位置。這時(shí)就要提到兩個(gè)重要概念:replaint和reflow。
replaint:屏幕的一部分重畫,不影響整體布局,比如某個(gè)CSS的背景色變了,但元素的幾何尺寸和位置不變。reflow:
意味著元件的幾何尺寸變了,我們需要重新驗(yàn)證并計(jì)算渲染樹。是渲染樹的一部分或全部發(fā)生了變化。這就是Reflow,或是Layout。
所以我們應(yīng)該盡量減少reflow和replaint,我想這也是為什么現(xiàn)在很少有用table布局的原因之一。
display:none 會(huì)觸發(fā) reflow,visibility: hidden屬性并不算是不可見屬性,它的語義是隱藏元素,但元素仍然占據(jù)著布局空間,它會(huì)被渲染成一個(gè)空框,所以visibility:hidden 只會(huì)觸發(fā) repaint,因?yàn)闆]有發(fā)生位置變化。
有些情況下,比如修改了元素的樣式,瀏覽器并不會(huì)立刻 reflow 或 repaint 一次,而是會(huì)把這樣的操作積攢一批,然后做一次 reflow,這又叫異步 reflow 或增量異步 reflow。
有些情況下,比如 resize 窗口,改變了頁面默認(rèn)的字體等。對(duì)于這些操作,瀏覽器會(huì)馬上進(jìn)行 reflow。
小結(jié)
本文我們就瀏覽器渲染流程逐步了解了一遍,相信大家一定都有所新的收獲,如果大家對(duì)于瀏覽器渲染流程還有任何疑問,歡迎反饋,我們共同交流,共同學(xué)習(xí),共同進(jìn)步。
作者:GavinHsueh,QQ/微信:753391279,專注網(wǎng)站建站、運(yùn)維及企業(yè)web應(yīng)用開發(fā)技術(shù)。
參考文獻(xiàn):
http://taligarsiel.com/Projec...
https://segmentfault.com/a/11...
https://sylvanassun.github.io...
https://www.zybuluo.com/lizla...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/93580.html
摘要:部分讀者向我反饋對(duì)于最后的瀏覽器渲染布局這塊不是很清晰,所以本文就瀏覽器渲染流程單獨(dú)開篇講解,希望大家都能有新的收獲。瀏覽器主要組件結(jié)構(gòu)瀏覽器主要組件渲染引擎和使用自主研發(fā)的渲染引擎。所以瀏覽器的渲染過程主要包括以下幾步解析生成樹。 在之前寫過的一篇《天龍八步細(xì)說瀏覽器輸入U(xiǎn)RL后發(fā)生了什么》一文中,和大家分享了從在瀏覽器中輸入網(wǎng)址URL到最終頁面展示的整個(gè)過程。部分讀者向我反饋對(duì)于最...
摘要:部分讀者向我反饋對(duì)于最后的瀏覽器渲染布局這塊不是很清晰,所以本文就瀏覽器渲染流程單獨(dú)開篇講解,希望大家都能有新的收獲。瀏覽器主要組件結(jié)構(gòu)瀏覽器主要組件渲染引擎和使用自主研發(fā)的渲染引擎。所以瀏覽器的渲染過程主要包括以下幾步解析生成樹。 在之前寫過的一篇《天龍八步細(xì)說瀏覽器輸入U(xiǎn)RL后發(fā)生了什么》一文中,和大家分享了從在瀏覽器中輸入網(wǎng)址URL到最終頁面展示的整個(gè)過程。部分讀者向我反饋對(duì)于最...
摘要:大家都知道是解釋型語言,既然是解釋型語言,就是編譯一行,執(zhí)行一行,那又何來預(yù)編譯一說呢腳本執(zhí)行引擎都做了什么呢今天我們就來看看吧。全局域就是一切聲明的全局變量,全是的屬性等同于函數(shù)預(yù)編譯發(fā)生在函數(shù)執(zhí)行前一刻。 大家都知道JavaScript是解釋型語言,既然是解釋型語言,就是編譯一行,執(zhí)行一行,那又何來預(yù)編譯一說呢?腳本執(zhí)行js引擎都做了什么呢?今天我們就來看看吧。 1-JavaScr...
摘要:的選擇器允許單個(gè)線程監(jiān)視多個(gè)輸入通道。一旦執(zhí)行的線程已經(jīng)超過讀取代碼中的某個(gè)數(shù)據(jù)片段,該線程就不會(huì)在數(shù)據(jù)中向后移動(dòng)通常不會(huì)。 1、引言 很多初涉網(wǎng)絡(luò)編程的程序員,在研究Java NIO(即異步IO)和經(jīng)典IO(也就是常說的阻塞式IO)的API時(shí),很快就會(huì)發(fā)現(xiàn)一個(gè)問題:我什么時(shí)候應(yīng)該使用經(jīng)典IO,什么時(shí)候應(yīng)該使用NIO? 在本文中,將嘗試用簡(jiǎn)明扼要的文字,闡明Java NIO和經(jīng)典IO之...
閱讀 3012·2021-11-22 12:06
閱讀 598·2021-09-03 10:29
閱讀 6526·2021-09-02 09:52
閱讀 2013·2019-08-30 15:52
閱讀 3411·2019-08-29 16:39
閱讀 1190·2019-08-29 15:35
閱讀 2061·2019-08-29 15:17
閱讀 1416·2019-08-29 11:17