DOMContentLoaded時間觸發與js,css,img的關聯
DOMContentLoaded觸發原理:
1、規範總是那麼的晦澀,但至少有一點是可以明確了的,就是在JS(不包括動態插入的JS)執行完之後,才會觸發DOMContentLoaded事件。
2、DOMContentLoaded事件本身不會等待CSS檔案、圖片、iframe載入完成。
它的觸發時機是:載入完頁面,解析完所有標籤(不包括執行CSS和JS),並如規範中所說的設定interactive
和執行每個靜態的script標籤中的JS,然後觸發。
而JS的執行,需要等待位於它前面的CSS載入(如果是外聯的話)、執行完成,因為JS可能會依賴位於它前面的CSS計算出來的樣式
實踐是檢驗真理的唯一標準
實踐是檢驗真理的唯一標準
實驗1:DOMContentLoaded事件不直接等待CSS檔案、圖片的載入完成
index.html:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title></title> <link rel="stylesheet" type="text/css" href="./css/main.css"> </head> <body> <p>Content</p> <img src="./img/chrome-girl.jpg"> </body> </html>
圖一
如果頁面中沒有script標籤,DOMContentLoaded事件並沒有等待CSS檔案、圖片載入完成。
Chrome開發者工具的Timeline面板可以幫我們記錄下瀏覽器的一舉一動。圖一中紅色小方框中的藍線,表示DOMContentLoaded事件,它右邊的紅線和綠線分別表示load事件和First paint,滑鼠hover在這些線露出灰色方框下面的一小部分時就會出現帶有說明文字的tips(這互動夠反人類的對吧!)。
實驗2:DOMContentLoaded事件需要等待JS執行完才觸發
index.html:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title></title> <script type="text/javascript"> console.timeStamp('Inline script before link in head'); window.addEventListener('DOMContentLoaded', function(){ console.timeStamp('DOMContentLoaded event'); }); </script> <link rel="stylesheet" type="text/css" href="./css/main.css"> <script type="text/javascript"> console.timeStamp('Inline script after link in head'); </script> </head> <body> <p>Content</p> <img src="./img/chrome-girl.jpg"> <script type="text/javascript" src="./js/main.js"></script> </body> </html>
main.js:
console.timeStamp('External script after link in body');
圖二
如果頁面中靜態的寫有script標籤,DOMContentLoaded事件需要等待JS執行完才觸發。
而script標籤中的JS需要等待位於其前面的CSS的載入完成。
console.timeStamp()
可以向Timeline中新增一條記錄,並對應上方的一條黃線。
從圖二中可以看出,在CSS之前的JS立刻得到了執行,而在CSS之後的JS,需要等待CSS載入完後才執行,比較明顯的是main.js早就載入完了,但還是要等main.css載入完才能執行。而DOMContentLoaded事件,則是在JS執行完後才觸發。滑動Timeline面板中表示展示區域的滑塊,如圖三,放大後即可看到表示DOMContentLoaded事件的藍線(之前跟黃線和綠線靠的太近了),當然,通過 console.timeStamp()
向TimeLine中新增的記錄也可證明其觸發時間。
圖三
現代瀏覽器會併發的預載入CSS, JS,也就是一開始就併發的請求這些資源,但是,執行CSS和JS的順序還是按原來的依賴順序(JS的執行要等待位於其前面的CSS和JS載入、執行完)。先載入完成的資源,如果其依賴還沒載入、執行完,就只能等著。
實驗3:img何時開始解碼、繪製?
從圖三中我們可以發現一個有趣的地方:img的請求老早就發出了,但延遲了一段時間才開始解碼。如圖二、圖三中的紅框所示,截圖中只框出了一部分表示解碼的記錄,而實際上這些表示解碼的記錄一直持續到img載入結束,如圖四所示,img是一邊載入一邊解碼的:
圖四
抱著“猜想——驗證”的想法,我猜想這是因為img這個資源是否需要展現出來,需要等 所有的JS和CSS的執行完 才知道,因為main.js可能會執行某些DOM操作,比如刪除這個img元素,或者修改其src屬性,而CSS可能會將其 display:
none
。
圖五
圖六
圖七
圖五中沒有JS和CSS,img的資料一接收到就馬上開始解碼了。
圖六中沒有JS,但img要等到CSS載入完才開始解碼。
圖七的程式碼跟圖六的程式碼唯一的區別是CSS把img給 display: none;
,這使得img雖然請求了,但根本沒有進行解碼。
這說明,img是否需要解碼、繪圖(paint)出來,確實需要等CSS載入、執行完才能知道。也就是說,CSS會阻塞img的展現!那麼JS呢?
圖八
圖八對應的程式碼:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript">
console.timeStamp('Inline script in head');
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"></script>
</body>
</html>
非常令人驚訝,在有JS而沒有CSS的頁面中,img居然能夠在收到資料後就立刻開始解碼、繪圖(paint),也就是說,JS並沒有阻塞img的展現!這跟我們以前理解的JS會阻塞img資源的傳統觀念不太一樣,看來Chrome對img的載入和展現做了新的優化。
我們常用的jQuery的 $(document).ready()
方法,就是對DOMContentLoaded事件的監聽(當然,其內部還會通過模擬DOMContentLoaded事件和監聽onload事件來提供降級方案)。通常推薦在DOMContentLoaded事件觸發的時候為DOM元素註冊事件。所以儘快的讓DOMContentLoaded事件觸發,就意味著能夠儘快讓頁面可互動:
- 減小CSS檔案體積,把單個CSS檔案分成幾個檔案以並行載入,減少CSS對JS的阻塞時間
- 次要的JS檔案,通過動態插入script標籤來載入(動態插入的script標籤不阻塞DOMContentLoaded事件的觸發)
- CSS中使用的精靈圖,可以利用對img的預載入,放在html中跟CSS檔案一起載入
在做實驗的過程中,感覺Chrome開發者工具的Timeline面板非常強大,瀏覽器的一舉一動都記錄下來。以前我們前端開發要想理解、探索瀏覽器的內部行為,或者摸著石頭過河的做黑盒測試,或者事倍功半的研究瀏覽器原始碼,唯一高效點的做法就是學習別人的研究經驗,看老外的文章,但瀏覽器的發展日新月異(比如這次實驗發現的JS不阻塞img的展現),別人的經驗始終不是最新、最適合的,關鍵是要結合自己的業務、需求場景,有針對性的做分析和優化。
相關推薦
DOMContentLoaded時間觸發與js,css,img的關聯
DOMContentLoaded觸發原理: 1、規範總是那麼的晦澀,但至少有一點是可以明確了的,就是在JS(不包括動態插入的JS)執行完之後,才會觸發DOMContentLoaded事件。 2、DOMContentLoaded事件本身不會等待CSS檔案、圖片、ifra
maven jetty 啟動後,不能修改靜態文件,js,css,html
9.4 拷貝 ram 啟動 maven pom jar包 conf text 解決辦法: 1.從jetty的jar包中(位置可能不同,有的jetty-web中)拷貝一份webdefault.xml文件 2.將webdefault.xml 中的useFileMappedBuf
web.xml中的dispatchservlet後,js,css,甚至gif都不能正常顯示
startup view details article 的人 核心 默認 href com 這個可以說是很多初學Springmvc的人都會碰到一個令人頭痛的問題 那就是為什麽我配置好web.xml中的dispatchservlet後,js,css,甚至gif都不能正常顯示
iOS 加載本地HTML,css,js
fill 簡書 p標簽 一道 bundle www string text orien 在IOS開發中,可以通過webView來加載HTML文件 步驟如下: 1.需要有一個webView,可以通過storyboard拖拽一個 或者 alloc 一個(我在這裏是拖拽了一個
前端過濾html,css,js
<div class="container-fluid"><!-- container-fluid --> <div class="row"> <div class="col-md-9">
JQuery使用load方法載入外部div時,css,js無效的辦法
問題: 一個html頁面a.html的js指令碼中,用$(‘selector’).load方法,載入另一個html頁面b.html中內容,b.html中css、js都失效。 解決辦法一: 第一步:在a.html的js指令碼中,使用load載入全部b.html,這樣b
python學習之網站的編寫(HTML,CSS,JS)(十七)----------示例,構造一個網頁的框架,上部標題,登入,logo,左側選單,右側內容,原始碼
結果: 顏色為了明顯,所以較為難看,可以根據自己的需要進行更改 原始碼: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title
python學習之網站的編寫(HTML,CSS,JS)(十六)----------示例,構造一個左側管理選單的功能,點選主選單才顯示下面的內容
結果: 程式碼: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>逆水行舟不進則退</title>
python學習之網站的編寫(HTML,CSS,JS)(十五)----------示例,彈出一個背景為半黑色,前面是白框的彈窗功能(已經編好的框架)
效果圖,程式碼直接可應用,按自己的需要在其中加入想要的內容: 程式碼及講解: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <
python學習之網站的編寫(HTML,CSS,JS)(十四)----------CSS的display行內標籤和塊級標籤的轉換,控制標籤是否顯示
行內標籤:有多大就佔多大,無法設定高度,寬度和邊距。 塊級標籤:佔一行,可以設定高度,寬度和邊距。 塊級標籤轉為行內標籤:display:inline 行內標籤轉為塊級標籤:display:block 還有一個特殊的轉換,既包含塊級標籤的屬性,又具有行內標籤的屬性,自己有多少佔多少,
python學習之網站的編寫(HTML,CSS,JS)(十三)----------CSS字型和對齊方式的設定
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>逆水行舟不進則退</title> </head> <b
python學習之網站的編寫(HTML,CSS,JS)(十二)----------CSS邊框的編寫
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>逆水行舟不進則退</title> </head> <b
python學習之網站的編寫(HTML,CSS,JS)(十一)----------如何利用其它html檔案中的CSS(也就是可以將共同的地方提取出來,放大一個檔案中,利於使用)
首先說一下它的具體用處,我們已經知道,當我們寫一個html檔案的時候,不同的標籤想用相同的版式的時候,我們可以將它提取出來,然後再用一些選擇器進行應用,比如class選擇器。但是,但我們編寫多個html檔案中的時候,多個檔案都想用一些相同的版式該怎麼辦呢? 那麼就引入了這種連線的方式,首先寫一個
python學習之網站的編寫(HTML,CSS,JS)(十)----------CSS中用的最多的class選擇器,批量的為一些標籤設定相同的版式
選擇器有很多種,有id選擇器,div選擇器,層級選擇器,組合選擇器等等,然而,用的最多的就是class選擇器,它的作用是為下面所有符合class規則的標籤設定上相同的版式。 步驟: 1.在頭部編寫<style>標籤,點+class選擇器的名稱(也就是下面需要選擇的class),然
python學習之網站的編寫(HTML,CSS,JS)(九)----------table標籤,表格的實現
table標籤,裡邊的tr表示行,td表示列。 程式碼: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>逆水行
python學習之網站的編寫(HTML,CSS,JS)(八)----------label標籤,點選label標籤的文字將編輯的游標移過來
如果不加label的話,只設置值的話,點選文字是不能將編輯的游標移過來的,必須將id連線上之後,才可以實現,點選文字就可以將編輯的游標移過來。 實現結果: 程式碼: <!DOCTYPE html> <html lang="en"> <hea
python學習之網站的編寫(HTML,CSS,JS)(七)----------以列表條目的方式顯示
話不多說,直接上圖 實現的程式碼及解釋: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>逆水行舟不進則退</t
FLEX與JS資料互動,以及Google外掛IFrame的使用
最近因為專案需要,用到的flex,同時需要與js做資料互動,同時還用到了Google的外掛IFrame,總結一點點自己的使用心得,其中很多資料都是在網上Google到的。 FLEX呼叫
html,css,js實現音樂播放,含音訊特效和歌詞
前端播放器樣例 有需要的小夥伴直接用就行:https://download.csdn.net/download/qq_34042417/10669205 實現思路: 1.載入完頁面後請求等到歌曲,歌詞檔案,要實現歌詞跟歌曲滾動則要求歌詞是lrc格式。 2.對歌詞處理,處理
python學習之網站的編寫(HTML,CSS,JS)(一)---------------------------------------初識(初學者需瞭解)
首先推薦一款很好的python編譯軟體pycharm,但凡接觸過python的人對它一定不是很陌生,在這裡我們就可以編輯一些瀏覽器認識的html檔案,創造出我們喜歡的網站頁面,在pycharm中建立一個html檔案是下面這樣的,然後我們會對其一句一句的解釋。 <!DO