深入理解DOMContentLoaded的触发时机

1,636 阅读2分钟

一、DOMContentLoaded的概念

当初始HTML文档已完全加载和解析时,将触发DOMContentLoaded事件,而不需要等待样式表,图像和子框架页面加载。与 window.onload 事件非常相似,但有一定区别:

  1. DOMContentLoaded 事件是在文档完全加载和解析之后触发
  2. window.onload 事件不但文档完全加载和解析完毕,相关资源都要加载完毕,比如图片和CSS文件等

二、HTML解析过程与DOMContentLoaded触发时机

1. 既无JS也无CSS的情况

image.png

image.png

2. 有CSS但无JS的情况

image.png

由图可见,DOMContentLoaded触发仍为DOM之后,无论此时CSS解析为CSSOM的过程是否完成。

3. 既有CSS也有JS的情况

image.png 上图描述的只包含了同步加载脚本的情况,然而对于JS的引用却不止一种方式,对于通过 async 和 defer 引用脚本,DOMContentLoaded触发时机存在差异:

(1)普通JS/sync(同步)

文档解析的过程中,如果遇到script脚本,就会停止页面的解析进行下载,当脚本都执行完毕后,才会继续解析页面。

image.png

(2)async(异步)

async 脚本会在加载完毕后执行,下面两种情况都是有可能发生的:

①HTML 还没有被解析完的时候,async 脚本已经加载完了;那么 HTML 停止解析,去执行脚本,脚本执行完毕后继续 HTML 加载与解析,HTML 解析完了之后触发 DOMContentLoaded 事件。

image.png

②HTML 解析完了之后,async脚本才加载完,然后再执行脚本;那么在HTML解析完毕、async 脚本还没加载完的时候就触发 DOMContentLoaded 事件。

image.png

(3)defer

文档解析时遇到设置了 defer 的脚本,就会在后台进行下载,但是并不会阻止文档的渲染,当页面解析和渲染完毕后,会等到所有的 defer 脚本加载完毕并按照顺序执行完毕才会触发 DOMContentLoaded 事件,下面两种情况都是有可能发生的:

①HTML 还没有被解析完的时候,defer脚本已经加载完了,那么 等待HTML 解析完成后执行脚本,脚本执行完毕后触发 DOMContentLoaded 事件。

image.png

②HTML 解析完了之后,defer脚本才加载完,然后再执行脚本,脚本执行完毕后触发 DOMContentLoaded 事件。

image.png