網(wǎng)頁渲染機(jī)制

如題,本文將簡介一下 瀏覽器對頁面的渲染的過程

一個網(wǎng)頁里面主要包含三大塊東西,Html/CSS/JavaScript。

一.先說幾個概念:

1.DOM:Document Object Model DOM:瀏覽器將HTML解析成樹形的數(shù)據(jù)結(jié)構(gòu),簡稱DOM。

2.CSSOM:CSS Object Model,瀏覽器將CSS代碼解析成樹形的數(shù)據(jù)結(jié)構(gòu)。

3.Render Tree:DOM樹和CSSOM樹連接在一起形成(稱之為)Render Tree(渲染樹)。

3.Layout:計算出Render Tree每個節(jié)點(diǎn)的具體位置。

4.Painting:通過顯卡,將Layout后的節(jié)點(diǎn)內(nèi)容分別呈現(xiàn)到屏幕上。

二.瀏覽器渲染過程

1.Create/Update DOM And request css/image/js:瀏覽器請求到HTML代碼后,在生成DOM的最開始階段(應(yīng)該是 Bytes → characters 后),并行發(fā)起css、圖片、js的請求,無論他們是否在HEAD里。

2.Create/Update Render CSSOM:CSS文件下載完成,開始構(gòu)建CSSOM。

3.Create/Update Render Tree:所有CSS文件下載完成,CSSOM構(gòu)建結(jié)束后,和 DOM 一起生成 Render Tree,Render Tree用來描述所有可見的DOM內(nèi)容,并且將CSSOM樣式信息附加到節(jié)點(diǎn)上。

為了形成渲染樹,瀏覽器大致做的事情有:

(1)從DOM樹根節(jié)點(diǎn)開始,遍歷每一個可見的節(jié)點(diǎn)

  • 一些節(jié)點(diǎn)是完全不可見的(比如 script標(biāo)簽,meta標(biāo)簽等),這些節(jié)點(diǎn) 會被忽略,因為他們不會影響渲染的輸出
  • 一些節(jié)點(diǎn)是通過CSS樣式隱藏了,這些節(jié)點(diǎn)同樣被忽略——例如某個元素的樣式指定為display:none;將被忽略。
  • 注意:“visibility:hidden”和“display:none”之間的不同:“visibility:hidden”將元素設(shè)置為不可見,但是同樣在布局上占領(lǐng)一定空間(例如,它會被渲染成為空盒子),“display:none”的元素是將節(jié)點(diǎn)從整個Render Tree中移除,所以不是布局中的一部分 。

(2)對每一個可見的節(jié)點(diǎn),找到合適的匹配的CSSOM規(guī)則,并且應(yīng)用樣式

(3)顯示可見節(jié)點(diǎn)(節(jié)點(diǎn)包括內(nèi)容和被計算的樣式)

4.Layout:有了Render Tree,瀏覽器已經(jīng)能知道網(wǎng)頁中有哪些節(jié)點(diǎn)、各個節(jié)點(diǎn)的CSS定義以及他們的從屬關(guān)系。Layout,顧名思義就是計算出每個節(jié)點(diǎn)在屏幕中的位置。

5.Painting:Layout后,瀏覽器已經(jīng)知道了哪些節(jié)點(diǎn)要顯示(which nodes are visible),每個節(jié)點(diǎn)的CSS屬性是什么(their computed styles),每個節(jié)點(diǎn)在屏幕中的位置是哪里(geometry)。就進(jìn)入了最后一步:Painting,按照算出來的規(guī)則,通過顯卡,把內(nèi)容畫到屏幕上。

  • 以上五個步驟前3個步驟之所有使用 “Create/Update” 是因為DOM、CSSOM、Render Tree都可能在第一次Painting后又被更新多次,比如JS修改了DOM或者CSS屬性。

  • Layout 和 Painting 也會被重復(fù)執(zhí)行,除了DOM、CSSOM更新的原因外,圖片下載完成后也需要調(diào)用Layout 和 Painting來更新網(wǎng)頁


三.CSS和JavaScript特性:

1.CSS會并發(fā)加載:瀏覽器解析http response 下載html文件會”自上而下“加載,并在加載過程中進(jìn)行解析渲染。加載過程中遇到外部css文件,瀏覽器另外發(fā)出一個請求,來獲取css文件。這里css解析會生成一個rule tree(規(guī)則樹),這個以后會更新。

2.JavaScript只能單獨(dú)加載:當(dāng)文檔加載過程中遇到j(luò)s文件,html文檔會掛起渲染(加載解析渲染同步)的線程,不僅要等待文檔中js文件加載完畢,還要等待解析執(zhí)行完畢,才可以恢復(fù)html文檔的渲染線程

四.JavaScript有哪些形式,可以放在什么地方?

  • 外部引入
    <body>...<script src="index.js"></script></body>

  • Html內(nèi)置
    <body>
    ...
    <script>
    alert(1);
    </script>
    </body>

注意:根據(jù)頁面渲染原理和JavaScript單獨(dú)加載的特性,以上兩種形式都需放置在<body>標(biāo)簽內(nèi)接近閉合標(biāo)簽的地方(head內(nèi)的js會阻塞頁面內(nèi)容的呈現(xiàn)及渲染,也會阻塞其后組件的下載,會導(dǎo)致“白屏”現(xiàn)象)

五.加載異步

  • 加關(guān)鍵字 defer或async,瀏覽器會立即加載并執(zhí)行指定腳本,“立即”指的是不等待后續(xù)文檔載入,讀到就加載并執(zhí)行。

1.async,加載和渲染后續(xù)文檔元素的過程將和script.js的加載與執(zhí)行并行進(jìn)行(異步)。

    <script async src="index.js"></script>        

2.defer,加載后續(xù)文檔元素的過程將和script.js的加載并行進(jìn)行(異步),但script.js的執(zhí)行要在所有元素解析完成之后DOMContentLoaded事件觸發(fā)之前完成。

    <script defer src="index.js"></script>                

defer和async作用:頁面引入其他網(wǎng)站代碼,引入的代碼不會影響當(dāng)前頁面的展現(xiàn)

注意
defer:腳本延遲到文檔解析和顯示后執(zhí)行,有順序。
async:不保證順序。

本文配圖及部分內(nèi)容來自于饑人谷,版權(quán)歸饑人谷_海瀚和饑人谷所有,轉(zhuǎn)載需說明來源
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容