HTML解析之DOMContentLoaded和onload

HTML解析之DOMContentLoaded和onload

HTML解析之DOMContentLoaded和onload

JS代码与body标签的位置关系
一个HTML初学时会遇到的问题,一个html页面中js代码应该放到哪里?

... 上面代码可以看出,如果js代码写在body标签前面,而且没用其他事件而直接获取dom的话是无法获取的。而js代码写在body标签的后面(里面的最后也可以)就可以获取dom。

实际上如果了解浏览器解析HTML规则就很清楚原因了,浏览器解析HTML由上往下依次执行,如果遇到

script标签的defer和async
从上面知道,浏览器解析HTML遇到script标签会阻塞。上面举例的JS代码都是内嵌在HTML中的,这样再解析到script时直接执行就行。但如果是引入外部JS文件的话会有一点不同,要先加载该JS文件,然后执行,然后在往下解析HTML。但script标签上还有两个常见属性defer和async

一般情况

defer

async

看图(图片来源于网络)

蓝色线代表网络读取,红色线代表执行时间,这俩都是针对脚本的;绿色线代表 HTML 解析。

总结defer和async的区别:

加载时是一样的,相对于HTML解析是异步的。
不同的是执行时机,async在代码加载完之后会马上执行,并且执行时会阻塞HTML解析。而defer则要等到文档解析DOM构建完成,DOMContentLoaded事件触发之前执行。
async执行时机不确定性,要注意使用场景。
所以script标签加上defer属性,即使不用DOMContentLoaded或window.onload也可以获取操作DOM。

//index.js
var box = document.getElementById(‘box’);
//可以获取到div
console.log(box); //div#box

...

DOMContentLoaded和window.onload
DomContentLoaded
MDN解释:当初始的 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,而无需等待样式表、图像和子框架的完成加载。另一个不同的事件 load 应该仅用于检测一个完全加载的页面。 在使用 DOMContentLoaded 更加合适的情况下使用 load 是一个令人难以置信的流行的错误,所以要谨慎。

注意:DOMContentLoaded 事件必须等待其所属script之前的样式表加载解析完成才会触发。

//index.css
#box{
width:100px;
height:100px;
background: pink;
}

//DOMContentLoaded前面引入样式表

上面代码看出,在DOMContentLoaded后面引入样式表,DOMContentLoaded可能无法获取样式表里的样式,因为此时HTML解析完成,DOM树构建完成,但外部css文件可能还没加载完成。

暂时得出结论:js代码应该放在样式表之后。

window.onload
这个就没什么好说的,此时HTML文档解析完成,其他依赖资源也全部加载完成。

用document.readyState看一下各种情况下的HTML文档状态:

//输出
//loading 文档加载中
//DOMCOntentLoaded interactive 文档与用户可以开始交互,可以操作DOM
//window.onload complete 一切完成

ready()简单实现
JQuery中有个$(document).ready(),下面就简单实现一下。

document.ready = function(fn){
if(document.addEventListener){ //现代浏览器
document.addEventListener(‘DOMContentLoaded’, function(){
document.removeEventListener(‘DOMContentLoaded’, arguments.callee, false);
fn();
}, false);
}else if(document.attachEvent){ //低版本IE
document.attachEvent(‘onreadystatechange’, function(){
if(document.readyState === ‘complete’){
document.detachEvent(‘onreadystatechange’, arguments.callee);
fn();
}
})
}else{
window.onload = fn;
}
}

总结
HTML文档加载步骤:

由上往下解析HTML结构。
遇到src属性则发起请求加载资源,只有script会阻塞HTML解析,其他(css、img等)都不会影响HTML解析。
script资源加载完,执行JS脚本。
DOM树构建完成,触发DOMContentLoaded
其他css、img、iframe等资源如果还未加载完成继续加载。
页面加载完毕,触发window.onload
为什么要强调css放头部,js放尾部
因为css样式表是浏览器渲染页面的重要一环,应该尽早发起请求加载,毕竟也不会阻塞HTML解析。

而HTML解析遇到script会阻塞,所以应该放到后面,而不阻塞其他资源请求。虽然说还是要等script加载执行完成之后才会触发DOMContentLoaded,但现在很多现代浏览器为了更好地用户体验,能够渲染不完整的dom树和cssom,尽快的减少白屏的时间。

原文链接:https://blog.csdn.net/samfung09/article/details/100753488

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值