頁面渲染機制(二)

前言

這是我本身在學習頁面渲染機制時以爲有用的知識點,而且融入了本身的思考梳理成了筆記css

上一篇 頁面渲染機制(一)html

渲染樹的構建

在 DOM 樹和 CSSOM 樹都渲染完成之後,就會開始構建渲染樹。渲染樹就是對 DOM 樹和 CSSOM 樹的 結合,獲得一個每一個節點對應什麼樣式的數據結構。這個結合的過程大致上是遍歷整個 DOM 樹,而後 在 CSSOM 樹裏查詢到匹配的樣式。渲染樹有如下幾個特色:面試

一、渲染樹的根節點是 HTML

在 Google Web Fundamentals 這個文檔中,渲染樹的根節點是 body,但實際上 HTML 節點上的樣式也是能夠顯示 在頁面上的,而 head 標籤裏的內容和顯示沒有關係,因此渲染樹中是沒有 head 標籤的部分瀏覽器

二、渲染樹和 DOM 樹的結構並不徹底一致

渲染樹裏會把全部不可見的元素忽略掉,因此若是 DOM 樹中的節點有 display: none;  屬性的節點以及它的子節點,最終都不會出如今渲染樹中。可是有 visibility: hidden;  樣式的元素會出如今渲染樹中,由於具備這個樣式的元素是須要佔位的,只不過不須要顯示出來bash

三、樣式優先級關係

同一個 DOM 節點可能會匹配到多個 CSSOM 節點,而最終的顯示由哪一個 CSS 樣式來肯定,就是樣式優先級的問題了。當一個 DOM 元素上有多個樣式的時候,樣式的優先級順序是:網絡

內聯樣式 > ID選擇器 > 類選擇器 > 標籤選擇器 > 通用選擇器 > 繼承樣式 > 瀏覽器默認樣式
複製代碼

還有一套計算優先級的方法,瀏覽器裏的每一個 CSS 選擇器都有一個權重值。須要肯定優先級時,直接用公司計算整條選擇器的權重做爲該樣式的優先級:數據結構

  • 內聯樣式的權重是1000
  • ID 選擇器裏樣式的權重是100
  • 類選擇器、屬性選擇器和僞類選擇器裏樣式的權重是10
  • 標籤選擇器裏樣式的權重是1
  • 通用選擇器直接忽略

假設一個選擇器裏有 a 個權重值是100、b 個權重值是10的選擇器,那麼這種選擇器的權重值就是 a100+b10佈局

Tips

一、計算模型僅供理解樣式優先級關係,不能表明瀏覽器裏真實的計算方法 二、權重值的計算不能越級,好比選擇器 A 有一個 ID 選擇器,權重是100;選擇器 B 用了20個類選擇器,權重值是 200。這個時候若是兩個選擇器應用在同一個 DOM 節點上,生效的會是 A 選擇器,由於它的選擇器級別更高 三、、若是兩個選擇器 A 和 B 是同級別選擇器,而且最終計算的權重值也相同,那麼這兩個選擇器誰在後面誰 優先級高post


佈局(Layout)

渲染樹構建好後,計算渲染樹上每一個節點的樣式,就能得出每一個元素所佔空間的大小和位置。這個過程就是佈局學習

繪製(Paint)

佈局以後,每一個元素的位置和大小就有了,通過最後繪製這一步,就能夠把樣式可視化的展現在屏幕上了。在繪製的過程當中,瀏覽器會調用圖形處理器,逐層逐塊的把全部計算好位置和樣式的元素都繪製出來

重排(Reflow)與重繪(Repaint)

渲染樹是動態構建的,DOM 節點和 CSS 節點的改動均可能會形成渲染樹的重建。渲染樹的改動就會形成重排或者重繪,下面咱們來介紹這兩個概念,以及它們都是在什麼狀況下會被觸發

一、重排

當咱們在 DOM 樹中新增、刪除了元素,或者是改變了某些元素的大小、位置、佈局方式等,在這個時候渲染樹裏 這個有改動的節點和它影響到的節點,都要從新計算。在改動發生時,要從新經歷 DOM 的改動、 CSSOM 樹的構 建、渲染樹的構建、佈局和繪製整個流程,這個過程就叫作 "重排",也叫作 "迴流"

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
  	<style> header { display: none; } </style>
</head>
<body>
    <header>
        <p>header</p>
    </header>
</body>
</html>
複製代碼

假設上述代碼已經繪製完畢了,這是咱們經過 JS 把 header 的 "display: none" 屬性去掉。這個時候會經歷如下過程:

  • DOM 沒有改動 不須要從新構建
  • CSSOM 樹中這個樣式節點裏的 display 屬性沒有了
  • 渲染樹中的變化就比較大了,不論是改動了 CSS 仍是 DOM 都會結合 DOM 樹和 CSSOM 樹從新構建一次。這也是爲何不推薦直接操做真實 DOM 元素的緣由
  • 佈局過程也有不小的開銷,須要給新加進來的 header 元素找到位置,再把其會影響到的全部元素的大小、位置從新計算一遍,獲得一個新的佈局
  • 最後就是按着新的佈局,把 header 和受它影響的元素都從新繪製一遍,這個頁面的改動就生效了

二、重繪

重繪是當咱們改變元素的字體顏色、背景色等外觀元素的時候,而且不會改變它的大小和位置,也不會影響到其餘元素的佈局。瀏覽器會直接對元素的樣式從新繪製,這個過程就叫作 "重繪"

還以上面的代碼爲例,假如要給 header 添加一個 "color: red;" 的樣式。這個時候會經歷一下過程:

  • DOM 沒有改動 不須要從新構建
  • CSSOM 樹中 header 對應的節點一個 "color: red;" 的樣式
  • 由於存在樣式繼承機制,因此瀏覽器還會找到 header 元素的子元素,若是有能夠繼承的節點,那麼也要給這些 節點加上 "color: red;" 的樣式,這個例子中就會在 header 裏的 p 元素上都加入 "color: red;" 的樣式
  • 位置沒有變更,不須要從新佈局
  • 對 header 元素及其子元素佔用的區域從新繪製

好了,這就是重排和重繪的概念了,相對來講,重排操做的消耗會比較大,因此在操做中最好儘可能少的形成頁面的重排

知識拓展

如何減小重排

能夠經過這幾種方式優化:

  • 不要逐項更改樣式,能夠把須要改的樣式收集在一塊兒,用一次操做改變
  • 用 class 的變更替代直接修改樣式
  • 不要循環操做 DOM,循環的結果也要換成起來,最後用一次操做來完成
  • 須要頻繁改動的元素(好比動畫)儘可能使用絕對定位,脫離文檔流的元素會減小對後面元素的影響
  • 在條件容許的狀況下儘可能的使用 CSS3 動畫,它能夠調用 GPU 執行渲染

面試題分享

下面給你們分享一些關於這一塊的面試題目,在這兩篇筆記中都能找到答案

  • 爲何 CSS  要放在 HTML  中靠前的 head  標籤中,而 JS  最好放在頁面的最後。這麼放對首屏時間和整個頁面

的加載時間都有什麼影響?

  • 爲何不推薦使用通配選擇器和標籤選擇器,它們的效率爲何會低?
  • 減小重排的方式有哪些?爲何要減小重排?
  • "display: none;" 和 "visibility: hidden;" 有什麼區別

ps: 這幾個面試題是在網絡上看到的,侵刪

小結

image.png
總結了一下,這兩篇關於頁面渲染機制的筆記大概講了這麼些東西。有什麼問題歡迎童鞋們來評論區留言討論,咱們一塊兒思考、學習、進步~
相關文章
相關標籤/搜索