一、DOMContentLoaded的概念
当初始HTML文档已完全加载和解析时,将触发DOMContentLoaded事件,而不需要等待样式表,图像和子框架页面加载。与 window.onload 事件非常相似,但有一定区别:
- DOMContentLoaded 事件是在文档完全加载和解析之后触发
- window.onload 事件不但文档完全加载和解析完毕,相关资源都要加载完毕,比如图片和CSS文件等
二、HTML解析过程与DOMContentLoaded触发时机
1. 既无JS也无CSS的情况
2. 有CSS但无JS的情况
由图可见,DOMContentLoaded触发仍为DOM之后,无论此时CSS解析为CSSOM的过程是否完成。
3. 既有CSS也有JS的情况
上图描述的只包含了同步加载脚本的情况,然而对于JS的引用却不止一种方式,对于通过 async 和 defer 引用脚本,DOMContentLoaded触发时机存在差异:
(1)普通JS/sync(同步)
文档解析的过程中,如果遇到script脚本,就会停止页面的解析进行下载,当脚本都执行完毕后,才会继续解析页面。
(2)async(异步)
async 脚本会在加载完毕后执行,下面两种情况都是有可能发生的:
①HTML 还没有被解析完的时候,async 脚本已经加载完了;那么 HTML 停止解析,去执行脚本,脚本执行完毕后继续 HTML 加载与解析,HTML 解析完了之后触发 DOMContentLoaded 事件。
②HTML 解析完了之后,async脚本才加载完,然后再执行脚本;那么在HTML解析完毕、async 脚本还没加载完的时候就触发 DOMContentLoaded 事件。
(3)defer
文档解析时遇到设置了 defer 的脚本,就会在后台进行下载,但是并不会阻止文档的渲染,当页面解析和渲染完毕后,会等到所有的 defer 脚本加载完毕并按照顺序执行完毕才会触发 DOMContentLoaded 事件,下面两种情况都是有可能发生的:
①HTML 还没有被解析完的时候,defer脚本已经加载完了,那么 等待HTML 解析完成后执行脚本,脚本执行完毕后触发 DOMContentLoaded 事件。
②HTML 解析完了之后,defer脚本才加载完,然后再执行脚本,脚本执行完毕后触发 DOMContentLoaded 事件。