页面生命周期内,有两个很是重要的事件: 1.DOMContentLoaded 此时浏览器已经彻底加载了HTML文件,而且DOM树已经生成好了。可是其余外部资源,如样式文件、图片、字体等并无加载好 2.Load 此时浏览器已经将全部的资源都加载完毕,能够正确读取页面中的资源。javascript
两个事件标识了两种不一样的时刻: 1.DOMContentLoaded DOM已经完成加载,此时能够为这些DOM元素绑定事件,初始化接口等 2.Load 其余外部资源均已加载完成,能够正确读出这些资源的信息,如图片的宽高等css
使用addEventListener
监听该事件:java
document.addEventListener('DOMContentLoaded', ready) 复制代码
举一个🌰浏览器
<script> function ready() { alert('DOM is ready'); var img = document.getElementById('img') // 因为图片属于外部资源,还没有下载完成,所以暂没法读到数据,因此结果是0x0 alert(`Image size: ${img.offsetWidth}x${img.offsetHeight}`); } document.addEventListener("DOMContentLoaded", ready); </script>  复制代码
虽然DOMContentLoaded
如咱们指望的那样工做,但仍在个别状况下有所不一样markdown
当解析器(HTML Paser)读取到<script>...</script>
内联标签时,会阻塞DOM构建,它会当即执行脚本,缘由是可能这些脚本会影响DOM,所以须要等到这些脚本都执行完成了,才会触发DOMContentLoaded
事件。 外部脚本(<script src="...">...</script>
)也是如此,浏览器须要等到加载后再执行完成才能够继续执行。dom
是否可让外部引用的脚本延后执行,答案是能够的。async
和defer
属性可让外部脚本延后执行,而不阻塞浏览器解析文档。async
和defer
仅在<script src="...">...</script>
情形下起做用,对内联脚本是无效的。用户能够在脚本完成加载前,就能够看到页面了,提高了用户体验。异步
async & defer
这两个属性都是告诉浏览器,标记的脚本不须要等待它加载完成,浏览器能够继续完成DOM构建和渲染 二者的区别以下:async
async | defer | |
---|---|---|
执行顺序 | 谁先完成下载谁先执行 | 执行顺序始终遵循加载的顺序,即便先下载完成了 |
DOMContentLoaded | 若是页面加载时间较长,脚本可能会先执行;绝大多数会在DOMContentLoaded以后执行,但必定是在Load事件以前执行 | 脚本会在DOMContentLoaded以前执行,但不阻塞浏览器加载和解析文档,即defer脚本与浏览器加载顺序无关前后 |
所以async
更符合一些应用场景。函数
对于外部样式文件而言,并不会影响到DOMCotentLoaded事件,它并不会等待外部样式文件加载完成。 可是!!!,若是DOMContentLoaded
所属的script以前出现的link样式,那么DOMContentLoaded
等待样式加载完成。以下:oop
<link type="text/css" rel="stylesheet" href="style.css"> <script> document.addEventListener("DOMContentLoaded", function(){ // ... }); </script> 复制代码
缘由是浏览器猜想脚本可能会读取一些样式信息,如位置、颜色,显然脚本就须要等到样式的加载完成了。
这个是顺便引出的话题,你知道浏览器内置的表单自动填充在何时完成么?没错,就是DOMContentLoaded触发的时候
当全部外部资源都完成加载后,浏览器触发load事件,此时能够读取外部资源信息了
<script> window.onload = function() { alert('Page loaded'); // image is loaded at this time alert(`Image size: ${img.offsetWidth}x${img.offsetHeight}`); }; </script> 复制代码
咱们一般能够经过DOMContentLoaded的时间去衡量一个页面加载的速度,由于此时用户已经能够看到这个页面,并能够有一些交互了。
以上提到的使用document.addEventListener
监听DOMCotentLoaded
事件,在IE9+都是有效的。须要兼容IE低版本
// 摘抄自jQuery源码 if ( document.readyState === "complete" || ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { // Handle it asynchronously to allow scripts the opportunity to delay ready window.setTimeout( jQuery.ready ); } 复制代码
比较粗暴,反复去嗅探是否能够执行ready函数。有兴趣去读读jQuery源码,颇有意思