DOMContentLoaded
当初始的 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,而无需等待样式表、图像和子框架的完成加载。—— MDN
虽然两者经常被拿来比较,但是两者在事件对象上就有很大的不同。DOMContentLoaded是 document 对象的触发事件,document常用的事件还有readyStateChange ;而 load 是 window 对象的事件,与它同属于window 对象的常用事件有:
- abort,用户放弃下载时触发
- beforeprint/afterprint,打印前后触发
- beforeunload,页面即将取消加载时触发
- blur,元素失去聚焦的时候触发
- storage,当localStorage 或者sessionStorage发生改变时触发
- unload ,当页面消失的时候触发。
通过查阅标准
我们知道,DOMContentLoaded 事件在触发之前
- 有一次 readyState 的变化,从 loading 到 interacitve。
- 所有节点从栈里弹出。
- 将静态的script执行完毕,动态script不会阻塞DOMContentLoaded 事件的触发。
- 然后就是触发 DOMContentLoaded 事件。
实验一
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Event Demo</title>
</head>
<body>
<p class="demo">hello</p>
<script>
console.log("script excuting, state is "+ document.readyState);
</script>
<script>
setTimeout(function() {
document.querySelector(".demo").style.color = "red";
console.log("element painting and the state is "+document.readyState);
},2000)
</script>
</body>
</html>
// js file
document.addEventListener("DOMContentLoaded", function (){
console.log("DOMContentLoaded event");
});
document.addEventListener("readystatechange", function (){
console.log("state change: now is: "+document.readyState);
});
// output
"script excuting, state is loading"
"state change: now is: interactive"
"DOMContentLoaded event"
"state change: now is: complete"
"element painting and the state is complete"
从实验可以看出:
- 在触发DOMContentLoaded 事件之前,readystatechange 事件被触发了一次,readyState 从loading 变到 interactive,DOMContentLoaded 触发后有触发了一次 readystatechange,readyStat 变成 complete。
- DOMContentLoaded 在静态脚本执行完毕之后(
script excuting
)才会触发。而动态的脚本(element painting
)并不会阻碍DOMContentLoaded 事件的触发。
load
根据标准,load事件是在readyState 为complete
之后才会触发,我们需要实践一下,在上方js file
的代码基础上加入:
window.addEventListener("load",function() {
console.log("load event");
});
将它放到先前代码前面,可以得到一下输出:
"script excuting, state is loading"
"state change: now is: interactive"
"DOMContentLoaded event"
"state change: now is: complete"
"load event"
"element painting and the state is complete"
也就是说,在readyState状态为complete
之后,才会触发load事件,然后才会执行到动态的script脚本。
从以上实验可以总结,readyState:loading -> 静态script 执行 -> readystatechange:interacitve -> DOMContentLoaded -> readystatechange:complete -> load -> 动态script
参考阅读
- whatwg.org, parsing.html#the-end
- AlloyTeam, JS、CSS以及img对DOMContentLoaded事件的影响