HTML渲染過程詳解

由于本人對http協議以及dns對url的解析問題并不了解,所以這里之探討url請求加載到瀏覽器端時,瀏覽器對html的解析到呈現過程,后來經過幾位道友分享,整理了一下url解析的過程,如下:

用戶輸入url地址,瀏覽器根據域名尋找IP地址
瀏覽器向服務器發送http請求,如果服務器段返回以301之類的重定向,瀏覽器根據相應頭中的location再次發送請求
服務器端接受請求,處理請求生成html代碼,返回給瀏覽器,這時的html頁面代碼可能是經過壓縮的
瀏覽器接收服務器響應結果,如果有壓縮則首先進行解壓處理,緊接著就是頁面解析渲染
解析渲染該過程主要分為以下步驟:

  1. 解析HTML
  2. 構建DOM樹
  3. DOM樹與CSS樣式進行附著構造呈現樹
  4. 布局
  5. 繪制

解析與構建DOM樹
前兩步我們放在一起討論,瀏覽器的實際工作也是將他們放在一起進行的。對于HTML瀏覽器有專門的html解析器來解析HTML,并在解析的過程中構建DOM樹。在這里我們討論兩種DOM元素的解析,即樣式(link、style)與腳本文件(script)。由于瀏覽器采用自上而下的方式解析,在遇到這兩種元素時都會阻塞瀏覽器的解析,直到外部資源加載并解析或執行完畢后才會繼續向下解析html。對于樣式與腳本的先后順序同樣也會影響到瀏覽器的解析過程,究其原因主要在于:script腳本執行過程中可能會修改html界面(如document.write函數);DOM節點的CSS樣式會影響js的執行結果。在我的測試中得到以下四條結論:
1)外部樣式會阻塞后續腳本執行,直到外部樣式加載并解析完畢。

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>JS Bin</title><script>var start = +new Date;</script><link href="http://udacity-crp.herokuapp.com/style.css?rtt=2" rel="stylesheet"></head><body><span id="result"></span><script>var end = +new Date;document.getElementById('result').innerHTML = (end-start);</script>
</body>
</html>

在這里插入圖片描述
2)外部樣式不會阻塞后續外部腳本的加載,但會阻塞外部腳本的執行。

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>JS Bin</title><script>var start = +new Date;</script><link href="http://udacity-crp.herokuapp.com/style.css?rtt=2" rel="stylesheet"></head><body>test<script src="http://udacity-crp.herokuapp.com/time.js?rtt=1&a"></script><div id="result"></div><script>var end = +new Date;document.getElementById("result").innerHTML = end-start;</script></body>
</html>主頁代碼
var loadTime = document.createElement('div');
loadTime.innerText = document.currentScript.src + ' executed @ ' + window.performance.now();
loadTime.style.color = 'blue';
document.body.appendChild(loadTime);

從瀑布圖中我們可以看到,外部腳本與外部樣式是并行加載,但直到外部樣式加載完畢,外部腳本才開始執行
 在這里插入圖片描述
3)如果后續外部腳本含有async屬性(IE下為defer),則外部樣式不會阻塞該腳本的加載與執行

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>JS Bin</title><script>var start = +new Date;</script><link href="http://udacity-crp.herokuapp.com/style.css?rtt=2" rel="stylesheet"></head><body>test<script src="http://udacity-crp.herokuapp.com/time.js?rtt=1&a" async></script><div id="result"></div><script>var end = +new Date;document.getElementById("result").innerHTML = end-start;</script></body>
</html>

從瀑布圖中可以看到外部腳本的加載與執行并不受link的阻塞
在這里插入圖片描述
4)對于動態創建的link標簽不會阻塞其后動態創建的script的加載與執行,不管script標簽是否具有async屬性,但對于其他非動態創建的script,以上三條結論仍適用

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>JS Bin</title><script>var start = +new Date;</script></head><body>test<script> var link = document.createElement('link');link.href = "http://udacity-crp.herokuapp.com/style.css?rtt=2";link.rel = "stylesheet";document.head.appendChild(link);var script = document.createElement('script');script.src = "http://udacity-crp.herokuapp.com/time.js?rtt=1&a";document.head.appendChild(script);</script><div id="result"></div><script>var end = +new Date;document.getElementById("result").innerHTML = end-start;</script></body>
</html>

這是最終頁面結構
 在這里插入圖片描述
通過瀑布圖與頁面結果可以看到動態創建的外部腳本并未受link的阻塞。
  在這里插入圖片描述
link或style標簽都會被解析成DOM節點。瀏覽器對于樣式表還會生成CSSStyleSheet對象(C++代碼),他集成子CSSStyle,指標是樣式表對象而不管該對象來自于Style還是link。該對象主要包含以下幾個重要屬性和方法

CSSRules 即css樣式代碼
type 表示樣式表類型的字符串。對CSS樣式表而言,這個字符串是“type/css”。
href 通過link生成的為樣式鏈接,否則為undefined
insertRule(rule,index):向cssRules集合中指定的位置插入rule字符串。IE不支持這個方法,但支持一個類似的addRule()方法。
deleteRule(index):刪除cssRules集合中指定的位置的規則。IE不支持這個方法,但支持一個類似的removeRule()方法。
文檔中對于所有的樣式表集合可以通過document.styleSheets來訪問。同時對于style或link DOM元素可以通過element.sheet來訪問CSSStyleSheet對象,IE中則通過element.styleSheet來訪問。

html解析完畢,DOM樹創建完成后DOMContentLoaded事件即觸發,這時候可以用過script來操作DOM節點。
構建呈現樹  
HTML解析完畢后,開始構建呈現樹RenderTree,這一步的主要工作在于將css樣式應用到DOM節點上,WebKit內核將這一過程稱為附著,其他瀏覽器有不同的概念。對前端工程師而言這個過程會涉及到CSS層疊問題。

首先將根據樣式重要性排序,由低到高依次為:

  1. 瀏覽器聲明
  2. 用戶普通聲明
  3. 作者普通聲明
  4. 作者重要聲明
  5. 用戶重要聲明

對于同一重要級別,則是根據CSS選擇符的特指度來判定優先級;一條樣式聲明的特指度由以下四個部分決定:S-I-C-E

  • 聲明來自內聯的style屬性則 S+1;
  • 聲明中含有id屬性則 I+1;
  • 聲明中含有類、偽類、屬性選擇器則 C+1;
  • 生命中含有元素、偽元素選擇器則 E+1;

特指度的比較類似于兩個字符串之間比較大小。

呈現樹的每一個節點即為與其相對應的DOM節點的CSS框,框的類型與DOM節點的display屬性有關,block元素生成block框,inline元素生成inline框。每一個呈現樹節點都有與之相對應的DOM節點,但DOM節點不一定有與之相對應的呈現樹節點,比如display屬性為none的DOM節點,而且呈現樹節點在呈現樹中的位置與他們在DOM樹中的位置不一定相同,比如float與絕對定位元素。

下圖為呈現樹與其相對應的DOM樹節點
  在這里插入圖片描述
布局

呈現樹構造完成后瀏覽器便進行布局處理,及計算每個呈現樹節點的大小和位置信息。有道友可能要問,前面已將樣式附著到DOM節點上,不是已經有了樣式信息為何還要計算大小。這里可以這樣理解,以上包含大小的樣式信息只是存在內存里,并沒有實際使用,瀏覽器要根據窗口的實際大小來處理呈現樹節點的實際顯示大小和位置,比如對于margin為auto的處理。

布局是一個遞歸過程,從跟呈現節點開始,遞歸遍歷子節點,計算集合幾何信息。具體過程還是比較復雜偶也不甚了解,道友們還是查閱其他資料吧。

繪制

布局完成后,便是將呈現樹繪制出來顯示在屏幕上。對于每一個呈現樹節點來說,主要繪制順序如下:

  1. 背景顏色
  2. 背景圖片
  3. 邊框
  4. 子呈現樹節點
  5. 輪廓

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/249841.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/249841.shtml
英文地址,請注明出處:http://en.pswp.cn/news/249841.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

grid布局

CSS Grid 布局CSS 中最強大的布局系統。與 flexbox 的一維布局系統不同&#xff0c;CSS Grid 布局是一個二維布局系統&#xff0c;也就意味著它可以同時處理列和行。通過將 CSS 規則應用于 父元素 (成為 Grid Container 網格容器)和其 子元素&#xff08;成為 Grid Items 網格項…

vue之router-view組件的使用

開發的時候有時候會遇到一種情況&#xff0c;比如 &#xff1a;點擊這個鏈接跳轉到其他組件的情況&#xff0c;通常會跳轉到新的頁面&#xff0c;蛋是&#xff0c;我們不想跳轉到新頁面&#xff0c;只在當前頁面切換著顯示&#xff0c;那么就要涉及到路由的嵌套了&#xff0c;也…

go 學習Printf

package main import "fmt" import "os" type point struct {x, y int } func main() { //Go 為常規 Go 值的格式化設計提供了多種打印方式。例如&#xff0c;這里打印了 point 結構體的一個實例。p : point{1, 2}fmt.Printf("%v\n", p) // {1 2…

博客園使用latex編輯公式

如何開啟數學公式編輯功能 開啟方法見下鏈接https://www.cnblogs.com/cmt/p/3279312.html 功能 支持數學公式塊支持文中數學公式DEMO $$ f(n) \begin{cases}\frac{n}{2}, & \text{if $n$ is even} \\3n1, & \text{if $n$ is odd}\end{cases} $$ 以上的代碼產生如下的公…

console.dir有很多瀏覽器,系統的兼容性問題,不要隨便用!

console.dir有很多瀏覽器&#xff0c;系統的兼容性問題&#xff0c;不要隨便用&#xff01; 要使用console.log();轉載于:https://www.cnblogs.com/bluestear/p/9400356.html

go 區分指針

先看一段代碼 先放一段代碼&#xff0c;人工運行一下&#xff0c;看看自己能做對幾題&#xff1f; package mainimport "fmt"func main() {var a int 1 var b *int &a var c **int &b var x int *b fmt.Println("a ",a) fmt.Println("&a…

ajax和axios、fetch的區別

1.jQuery ajax $.ajax({type: POST,url: url,data: data,dataType: dataType,success: function () {},error: function () {} });傳統 Ajax 指的是 XMLHttpRequest&#xff08;XHR&#xff09;&#xff0c; 最早出現的發送后端請求技術&#xff0c;隸屬于原始js中&#xff0c…

函數函數sigaction、signal

函數函數sigaction 1. 函數sigaction原型&#xff1a; int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); 分析&#xff1a; 參數 signum &#xff1a;要捕獲的信號。參數act&#xff1a;truct sigaction 結構體&#xff0c;后面具體講解傳入…

使用SQL Server連接xml接口,讀取并解析數據

--數據源格式&#xff0c;放到任意程序中部署接口即可--<Data xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd"http://www.w3.org/2001/XMLSchema"> --<Peoples> --<People> --<Name>張三</Name> --<S…

mac 卸載編輯器卸不干凈

Configuration~/Library/Preferences/Caches~/Library/Caches/Plugins~/Library/Application Support/Logs~/Library/Logs/轉載于:https://www.cnblogs.com/smzd/p/10114540.html

vue中使用axios最詳細教程

前提條件&#xff1a;vue-cli 項目 安裝&#xff1a; npm npm 在main.js導入&#xff1a; // 引入axios&#xff0c;并加到原型鏈中 import axios from axios; Vue.prototype.$axios axios; import QS from qs Vue.prototype.qs QS;封裝好的axios,拿走不送&#xff1a;&am…

Java 類型轉換String,List,Map,Array

1. JsonString轉為Map String jsoNStr "{\n" "\t\"TestArray\": [\"1\", \"2\", \"3\"]\n" "}";Map map JSON.parseObject(jsoNStr,Map.class);2.Object轉為JsonArray(得保證obj是個Array數組&#x…

關于固件

固件(Firmware)就是寫入EROM或EPROM(可編程只讀存儲器)中的程序&#xff0c;通俗的理解就是“固化的軟件”&#xff0c;臺港澳稱為“韌體”。更簡單的說&#xff0c;固件就是BIOS的軟件&#xff0c;但又與普通軟件完全不同&#xff0c;它是固化在集成電路內部的程序代碼&#x…

React-Native 指定模擬器RUN-IOS

react-native run-ios --simulator "iPhone 7” 轉載于:https://www.cnblogs.com/smzd/p/10185263.html

vue和element-ui使用

上一篇已經創建好一個vue項目。https://mp.csdn.net/postedit/80926242 這一篇主要是創建一個vue項目并結合餓了么框架element-ui。 1.先創建vue項目&#xff0c;我準備把項目放在e盤下&#xff1a;E:\Work\RegisterProject&#xff1b; 命令行進入這個目錄&#xff1a; 創…

javaweb學習6——自定義標簽

聲明&#xff1a;本文只是自學過程中&#xff0c;記錄自己不會的知識點的摘要&#xff0c;如果想詳細學習JavaWeb&#xff0c;請到孤傲蒼狼博客學習&#xff0c;JavaWeb學習點此跳轉 本文鏈接&#xff1a;https://www.cnblogs.com/xdp-gacl/p/3916946.html https://www.cnblogs…

goland 實用鍵

代碼補全 option command v轉載于:https://www.cnblogs.com/smzd/p/10313417.html

關于Mysql java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES)的問題...

問題所在&#xff1a; 1.連接數據庫一個是密碼是否正確&#xff0c; 2.driver是否對&#xff0c; 3.有么有jar包沖突&#xff0c;轉載于:https://www.cnblogs.com/java-123/p/9403412.html

vscode配置vue環境

一、安裝VSCode、NodeJS VSCode&#xff1a;https://code.visualstudio.com/ NodeJS&#xff1a;https://nodejs.org/en/ 二、打開VSCode&#xff0c;安裝常用插件 如圖所示&#xff08;安裝后重新加載即可&#xff09;: 三、項目中添加.vscode文件夾&#xff0c;文件夾中添…

秒殺核心設計(減庫存部分)-防超賣與高并發

商品詳情頁面的靜態化&#xff0c;varnish加速&#xff0c;秒殺商品庫獨立部署服務器這種就略過不講了。只討論庫存部分的優化 mysql配置層面的優化可以參考我的這篇文章 《關于mysql innodb引擎性能優化的一點心得》 重點設計在數據庫層面。 2張表&#xff1a; 第一張&#xf…