这两个是 jQuery 中的方法,对应原生的代码分别是 window.onload
、window.addEventListener('DOMContentLoaded', fn)
。
DOMContentLoaded
DOMContentLoaded不同的浏览器对其支持不同,所以在实现的时候我们需要做不同浏览器的兼容。
-
支持 DOMContentLoaded 事件的,就使用 DOMContentLoaded 事件。
-
IE6、IE7不支持 DOMContentLoaded ,但它支持 onreadystatechange 事件。
更低的 ie 还有个特有的方法doScroll, 通过间隔调用:document.documentElement.doScroll("left"); 可以检测 DOM 是否加载完成。当页面未加载完成时,该方法会报错,直到 doScroll 不再报错时,就代表 DOM 加载完成了。该方法更接近 DOMContentLoaded 的实现。
load
所有资源加载完成,包含图片、音频、视频。所以 load 触发时机是晚于 DOMContentLoaded。
为什么要求把 JS 放在末尾? 既然 DOM 树完全生成好后页面才能渲染出来,浏览器又必须读完全部 HTML 才能生成完整的 Dom 树,script 标签不放在 body 底部是不是也一样,因为 DOM 树的生成需要整个文档解析完毕。
现代浏览器为了更好的用户体验,渲染引擎将尝试尽快在屏幕上显示的内容。它不会等到所有 HTML 解析之前开始构建和布局渲染树。部分的内容将被解析并显示。也就是说浏览器能够渲染不完整的 DOM 树和 CSSOM,尽快的减少白屏的时间。假如我们将 JS 放在 header,JS 将阻塞解析 DOM,DOM 的内容会影响到 First Paint,导致 First Paint 延后。所以说我们会将 JS 放在后面,以减少 First Paint 的时间,但是不会减少 DOMContentLoaded被触发的时间。