1、概念css
當初始的 HTML 文檔被徹底加載和解析完成以後,DOMContentLoaded 事件被觸發,而無需等待樣式表、圖像和子框架的完成加載。html
load 僅用於檢測一個徹底加載的頁面,頁面的html、css、js、圖片等資源都已經加載完以後纔會觸發 load 事件。瀏覽器
2、瀏覽器的一些基本概念數據結構
瀏覽器將資源下載到本地的過程。框架
解析的意思是將一個元素經過必定的方式轉換成另外一種形式。
好比 html 的解析。首先要明確,html 下載到瀏覽器的表現形式就是包含字符串的文件。瀏覽器將 html 文件裏面的字符串讀取到內存中,按照 html 規則,對字符串進行取詞編譯,將字符串轉化成另外一種易於表達的數據結構。異步
好比下面的代碼:fetch
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>只有css</title> <link rel="stylesheet" href="./index.css" /> </head> <body> <div id="div1"></div> <link rel="stylesheet" href="./c1.css" /> <link rel="stylesheet" href="./c3.css" /> <script src="http://test.com:9000/mine/load/case2/j1.js "></script> <link rel="stylesheet" href="./c4.css" /> <div id="div2"></div> </body> </html>
瀏覽器會對這個 html 文件進行編譯,轉化成相似下面的結構:ui
瀏覽器會對轉化後的數據結構自上而下進行分析:首先開啓下載線程,對全部的資源進行優先級排序下載(注意,這裏僅僅是下載)。同時主線程會對文檔進行解析: spa
⚠️在 body 中第一個 script 資源下載完成以前,瀏覽器會進行首次渲染,將該 script 標籤前面的 DOM 樹和 CSSOM 合併成一棵 Render 樹,渲染到頁面中。這是頁面從白屏到首次渲染的時間節點。線程
將文檔中的全部 DOM 元素構建成一個樹型結構,DOM 構建是自上而下進行構建的,會受到 js 執行的干擾。
CSS 構建
將文檔中的全部CSS資源合併。
將 DOM 樹和 CSS 合併成一棵渲染樹,render 樹在合適的時機會被渲染到頁面中。
3、HTML文檔的加載與頁面的首次渲染
一、瀏覽器首先下載該地址所對應的 html 頁面。
二、瀏覽器解析 html 頁面的 DOM 結構。
三、開啓下載線程對文檔中的全部資源按優先級排序下載。
四、主線程繼續解析文檔,到達 head 節點 ,head 裏的外部資源是外鏈樣式表和外鏈 js。
五、解析到 body
body 裏的狀況比較多,body 裏可能只有 DOM 元素,可能既有 DOM、也有 css、js 等資源,js 資源又有可能異步加載圖片、css、js 等。DOM 結構不一樣,瀏覽器的解析機制也不一樣,因此須要分開來討論。
六、文檔解析完畢,頁面從新渲染。當頁面引用的全部 js 同步代碼執行完畢,觸發 DOMContentLoaded 事件。
七、html 文檔中的圖片資源,js 代碼中有異步加載的 css、js 、圖片資源都加載完畢以後,load 事件觸發。
以下代碼所示:
<body> <!-- 白屏 --> <div id="div1"></div> <!-- 白屏 --> <link rel="stylesheet" href="./c1.css" /> <!-- 白屏 --> <link rel="stylesheet" href="./c3.css" /> <!-- 若是此時 j1.js 還沒有下載到本地,則首次渲染,此時的 DOM 樹 只有 div1 ,因此頁面上只會顯示 div1,樣式是 c1.css 和 c3.css 的並集。--> <!-- 若是此時 j1.js 已經下載到本地,則先執行 j1.js,頁面不會渲染,因此此時仍然是白屏。--> <!--下面的 js 阻塞了 DOM 樹的構建,因此下面的 div2 沒有在文檔的 DOM 樹中。 --> <script src="http://test.com:9000/mine/load/case2/j1.js "></script> <!-- j1.js 執行完畢,繼續 DOM 解析,div2 被構建在文檔 DOM 樹中,此時頁面上有了div2 元素,樣式仍然是 c1.css 和 c3.css 的並集 --> <link rel="stylesheet" href="./c4.css" /> <!-- c4.css 加載完畢,從新構建render樹,樣式變成了 c1.css、c3.css 和 c4.css 的並集 --> <div id="div2"></div> <script> // 利用 performance 統計 load 加載時間。 window.onload=function(){console.log(performance.timing.loadEventStart - performance.timing.fetchStart);} </script> </body>
4、DomContentLoaded 事件的觸發
DOMContentLoaded 事件在 html文檔加載完畢,而且 html 所引用的內聯 js、以及外鏈 js 的同步代碼都執行完畢後觸發。
5、load 事件的觸發
當頁面 DOM 結構中的 js、css、圖片,以及 js 異步加載的 js、css 、圖片都加載完成以後,纔會觸發 load 事件。