前端的純技術就是對規範的認知
什麼是domcontentloaded 事件?
首先想到的是查看w3c的html5規範,domcontentloaded::
用戶代理停止解析文檔後,用戶代理必須運行以下步驟:
1。將當前文檔準備就緒設置為“交互式”,並將插入點設置為未定義。
將所有節點從開放元素的堆棧中彈出。
2。如果在文檔完成解析時將執行的腳本列表不是空的,請運行以下代替:
2.1旋轉事件循環,直到文檔完成後將執行的腳本列表中的第一個腳本具有“準備好被解析為執行”標誌集,而解析器的文檔沒有阻止腳本的樣式表。
2.2在文檔完成解析後將執行的腳本列表中執行第一個腳本。
2.3從文檔完成解析後將執行的腳本列表中刪除第一個腳本元素(即列出列表中的第一個條目)。
2.4如果在文檔完成解析時將執行的腳本列表仍然沒有空,請再次從orpetep 1重複這些替代。
3.將一個簡單事件的任務排隊,該事件在文檔中燃燒了名為domcontent的泡沫。
規範總是那麼的晦澀,但至少有一點是可以明確了的
接下來看看mdn上有關domcontentloaded::
當文檔被完全加載和解析時,將發射domcontentloaded事件,而無需等待樣式表,圖像和子幀以完成加載
注意:StylesHeet加載屏幕腳本執行,因此,如果您有
<script>在<link rel="stylesheet" ...>之後,該頁面將無法完成解析,並且在加載樣式表之前,該頁面將不會觸發。
這麼看來,至少可以得出這麼一個理論:domcontentloaded事件本身不會等待css 文件、圖片、 iframe加載完成。
它的觸發時機是:加載完頁面,解析完所有標籤(不包括執行 css和js),並如規範中所說的設置interactive和執行每個靜態的腳本標籤中的js,然後觸發。
而js的執行,需要等待位於它前面的css 加載(如果是外聯的話),因為,因為
實踐是檢驗真理的唯一標準
實驗1:domcontent負載事件不直接等待css 文件、圖片的加載完成
index.html:
<! doctype html> <html lang =“ zh-cn”> <head> <meta charset =“ utf-8”> <title> </title> </title> <link rel =“ stylesheet” type =“ text/css” text/css“ href =” ./ src =“ ./ img/chrome-girl.jpg”> </body> </html>
圖一
如果頁面中沒有腳本標籤,domcontentloaded事件並沒有等待CSS文件、圖片加載完成。
chrome開發者工具的時間軸面板可以幫我們記錄下瀏覽器的一舉一動。圖一中紅色小方框中的藍線,表示domcontentloaded事件,它右邊的紅線和綠線分別表示負載事件和第一個油漆,鼠標懸停在這些線露出灰色方框下面的一小部分時就會出現帶有說明文字的提示(這交互夠反人類的對吧!)。 )
實驗2:domcontent負載事件需要等待js執行完才觸發
index.html:
<! doctype html> <html lang =“ zh-cn”> <head> <head> <meta charset =“ utf-8”> <title> </title> </title> <script type =“ text/javascript”> console.timestamp('innline script inline script in link in Heard in in hears in in hears'in in hears'); window.addeventListener('domcontentloaded',function(){console.timestamp('domcontentloaded event'');}); </script> <link rel =“ stylesheet” type =“ text/css” href =“ ./ css/main.css” rel =“外部nofollow” rel =“ nofollow”> <script ofert nofollow'> <script type =“ text/javascript”> console.timestamp(timestamp) </script> </head> <body> <p> content </p> <img src =“ ./ img/chrome-girl.jpg”> <script type =“ text/javascript” src =“ ./ js/main.js”>main.js:
console.timestamp(“身體中的鏈接後的外部腳本”);
圖二
如果頁面中靜態的寫有腳本標籤,domcontentloaded事件需要等待js執行完才觸發。
而腳本標籤中的js需要等待位於其前面的css的加載完成。
console.timestamp()可以向時間軸,並對應上方的一條黃線。 ,並對應上方的一條黃線。
從圖二中可以看出,在cs之前的js立刻得到了執行,css之後的js,需要等待css加載完後才執行
圖三
CSS,JS,也就是一開始就並發的請求這些資源,但是
實驗3:img 何時開始解碼、繪製?
從圖三中我們可以發現一個有趣的地方:img的請求老早就發出了,但延遲了一段時間才開始解碼。如圖二、圖三中的紅框所示,截圖中只框出了一部分錶示解碼的記錄,而實際上這些表示解碼的記錄一直持續到
圖三
CSS,JS,也就是一開始就並發的請求這些資源,但是
實驗3:img 何時開始解碼、繪製?
從圖三中我們可以發現一個有趣的地方:img的請求老早就發出了,但延遲了一段時間才開始解碼。如圖二、圖三中的紅框所示,截圖中只框出了一部分錶示解碼的記錄,而實際上這些表示解碼的記錄一直持續到
圖四
抱著“猜想” - 驗證的想法,我猜想這是因為,我猜想這是因為img這個資源是否需要展現出來,需要等所有的js和css的執行完display: none知道,因為main。
圖五
圖六
圖七
圖五中沒有js和css,img的數據一接收到就馬上開始解碼了。
圖六中沒有js,但img要等到css加載完才開始解碼。
CSS把img給display: none; ,這使得img雖然請求了,但根本沒有進行解碼。 ,但根本沒有進行解碼。
這說明,img 是否需要解碼、繪圖(油漆)出來,確實需要等,css 加載、執行完才能知道。也就是說
圖八
圖八對應的代碼:
<! doctype html> <html lang =“ zh-cn”> <head> <head> <meta charset =“ utf-8”> <title> </title> </title> <script type =“ text/javascript”> console.timestamp('head'inline script'in Heard'); window.addeventListener('domcontentloaded',function(){console.timestamp('domcontentloaded event'');}); </script> </head> <body> <p> content </p> <img src =“ ./ img/chrome-girl.jpg”> <script type =“ text/javascript” src =“ ./ js/main.js”>非常令人驚訝,在有js而沒有css的頁面中,img 居然能夠在收到數據後就立刻開始解碼、繪圖(油漆),也就是說
我們常用的jQuery的$(document).ready()方法,就是對domcontentloaded 事件的監聽(當然,其內部還會通過模擬domcontentloaded事件和監聽事件和監聽事件和監聽(ONLOAD)。通常推薦在domcontentloaded domcontentloaded dom domdom元素註冊事件。所以盡快的讓domcontloadeddomcontentloaded事件觸發
CSS文件體積,把單個css文件分成幾個文件以並行加載,減少css對js的阻塞時間
次要的jS文件,通過動態插入
CSS中使用的精靈圖,可以利用對img的預加載,放在html中跟CSS文件一起加載
在做實驗的過程中,感覺chrome開發者工具的時間軸,瀏覽器的一舉一動都記錄下來。以前我們前端開發要想理解、探索瀏覽器的內部行為,瀏覽器的一舉一動都記錄下來。以前我們前端開發要想理解、探索瀏覽器的內部行為,或者事倍功半的研究瀏覽器源碼,唯一高效點的做法就是學習別人的研究經驗,看老外的文章,看老外的文章
PS。
以上測試環境為Windows/Chrome,並用提琴手模擬慢速網絡