domLoading
浏览器开始解析dom树的时间点
domInteractive
表示浏览器已经解析好dom树了。
domContentLoaded
同步的JS已经执行完毕了。
这里需要再解释一点:
由于同步JS会阻塞Dom的解析,因此在有同步JS的情况下,domInteractive和domContentLoaded的区别不大。
如果JS添加了defer属性,那么domInteractive和domContentLoaded的时间差取决于JS的下载和执行时间。defer JS表示告诉浏览器,这段JS在domInteractive后执行。见http://www.w3.org/TR/html5/syntax.html 。一旦执行完defer JS,就会触发domContentLoaded.
如果JS属性为async,那么domContentLoaded和domInteractive又几乎没什么区别了,因为js的解析不会阻塞dom,也不阻塞domContentLoad事件。
onload
页面上的元素已经加载完毕了。包括所有CSS, JS, Image等等。
一些小实验
疑问1:同步的JS通过document.write写入JS script会不会延迟DomContentLoaded?
结论:会。从例子中可以看到,DomContentLoaded必须等到同步写入的JS文件写完才触发。
代码:
<html>
<head>
</head>
<body>
<script>
document.write('<script src="t/wait-3s.js"' + '></' + 'script>');
</script>
{{flush 1000}}
<h1>Hello World</h1>
</body>
</html>
时间线:
疑问2: 同步的JS动态插入defer JS会不会延迟DomContentLoaded?
结论:不会延迟comContentLoaded,但会阻塞onload的时间。需要补充的是,即便是动态插入没有defer的JS,也不会延迟DomContentLoaded.
对于如下代码:
<html>
<head>
</head>
<body>
<script>
var script = document.createElement('script');
script.src= "/t/wait-2s.js";
script.defer = true;
document.head.appendChild(script);
</script>
{{flush 1000}}
<h1>Hello World</h1>
</body>
</html>
时间线如下:(蓝色为主文档,黄线为JS文件)
疑问3:如果在domContentLoaded的时刻动态插入(同步/defer/async)的script,会不会阻塞onload事件?
结论:(同步/defer/async)均会阻塞onload事件。
代码(以defer为例):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script>
document.addEventListener('DOMContentLoaded', function(){
var script = document.createElement('script');
script.src= "/t/wait-2s.js";
script.defer = true;
document.head.appendChild(script);
});
</script>
{{flush 1000}}
<h1>Hello World</h1>
</body>
</html>
时间线:
上面的两个小实验应证的是规范中的:Spin the event loop until the
set of scripts that will execute as soon as possibleandthe list of scripts that will execute in order as soon as possibleare empty.
疑问三:如果在domContentLoaded时动态插入CSS/图片/iframe,会阻塞onload事件吗?
结论:会阻塞。动态插入的图片/CSS会阻塞onload事件,iframe不会。
代码(以image为例):
<html>
<head>
</head>
<body>
<script>
document.addEventListener('DOMContentLoaded', function(){
var img = document.createElement('img');
img.src= "/t/wait-2s.png";
document.body.appendChild(img);
/*
var link = document.createElement('link');
link.rel = "stylesheet";
link.href = "t/wait-3s-red.css";
document.body.appendChild(link);
*/
/*
var iframe = document.createElement('iframe');
iframe.src = "t/wait-3s.html";
document.body.appendChild(iframe);
*/
});
</script>
{{flush 1000}}
<h1>Hello World</h1>
</body>
</html>
结果:
【更多待补充...】