前言:時間線在js中占很重要的地位:優化DOM、邏輯正確時輸出的為什么是undefind,很有可能都是時間線在作祟 (ps:對象調用錯時也會是undefind
(1)先加載loading事件,再解析頁面
<div class="demo" style="width:100px;height: 100px;background: red;"></div>
<script>
console.log(document.readyState)
</script>
(2)以下輸出的是undefind,為什么是這樣?因為等全部加載完再執行。它們之間有個時間差。所以
<script>
var div = document.getElementsByTagName('div')[0];
console.log(div);
</script>
<div class="demo" style="width:100px;height: 100px;background: red;"></div>
(3)以下輸出DOM,解析完立馬加載dom,不用等它全部加載完 只有DOMContentLoaded才能寫在上面
<script>
document.addEventListener('DOMContentLoaded',function(){
var div = document.getElementsByTagName('div')[0];
console.log(div);
},false)
</script>
<div class="demo" style="width:100px;height: 100px;background: red;"></div>
(4)最快的解析的方式是把script寫在下面,效率最高的方法
<div class="demo" style="width:100px;height: 100px;background: red;"></div>
<script>
document.addEventListener('DOMContentLoaded',function(){
var div = document.getElementsByTagName('div')[0];
console.log(div);
},false)
</script>
2.遇到link外部css,創建線程加載,並繼續解析文檔。
3.遇到script外部js,並且沒有設置async、defer,瀏覽器加載並阻塞,等待js加載完成並執行該腳本,然后解析解析文檔
4.遇到script外部js,並且設置有async、defer,瀏覽器創建線程加載,並繼續解析文檔。異步必須禁止使用document.write。
對於async屬性的腳本,腳本加載完成后立即執行。
<div class="demo" style="width:100px;height: 100px;background: red;"></div>
<script>
window.onload = function (){
document.write('a')
}
</script>
onload方法是在一定清空下有消除文檔流的功能,看以下是不是沒有執行div方塊,把div方塊在標簽里刪了,只有一個a
5、遇到img等,先正常解析dom結構,然后瀏覽器異步加載src,並繼續解析文檔。
6.當文檔解析完成,document.readyState = 'interactive'。解析完不代表加載完成。
7、文檔解析完成后,所有設置有defer的腳本會按照順序執行。(注意與async的不同,但同樣禁止使用document.write()); defer:推遲 ps:和第六步同時發生,當defer執行完會執行第六步
8.
document對象觸發DOMContentLoaded事件,這也標志着程序執行從同步腳本執行階段,轉化為事件驅動階段。 ps:當瀏覽器解析完之后就會執行事件,
9.
當所有async的腳本加載完成並執行后、img等加載完成后,document.readyState = 'complete',window對象觸發load事件。 complete:完成 ps:等所有加載完在加載一次,改成完成狀態,window觸發load對象。
例:
<div class="demo" style="width:100px;height: 100px;background: red;"></div>
<script>
window.onload = function (){ //觸發load事件
console.log(document.readyState);
}
console.log(document.readyState);
運行:從下圖可以看出,先執行的是loading事件
10.
從此,以異步響應方式處理用戶輸入、網絡事件等。
大致 步驟:創建document對象(加載loading) -- 文檔解析完 --- 文檔解析完並加載、執行完。
<div class="demo" style="width:100px;height: 100px;background: red;"></div>
<script>
console.log(document.readyState);
document.onreadystatechange = function (){
console.log(document.readyState);
}
</script>
有一個DOMContentLoaded事件是等解析完就執行的事件。
例:
<div class="demo" style="width:100px;height: 100px;background: red;"></div>
<script>
console.log(document.readyState);
document.onreadystatechange = function (){
console.log(document.readyState);
}
document.addEventListener('DOMContentLoaded',function(){
console.log('123')
},false)
運行結果:
從上圖可以看出,在解析之后立馬輸出123。解析完才執行主函數(函數體)函數體如下:
$(document).ready(function (){
})
window等加載完再觸發之后的事件,有點慢,可以使用DOMContentLoaded寫,因為它是解析完就加載