domReady是名为DOMContentLoaded事件的别称,当初始的HTML文档被完全加载和解析完成之后,DOMContentLoaded事件被触发,而无需等待样式表、图像和子框架的完全加载。
浏览器渲染DOM结构是有一定顺序的,虽然不同浏览器的实现各有不同,但是基本流程都大致相同:
HTML标签,生成DOM Tree。<link>或者<style>标签时,开始解析CSS,生成CSSOM,值的注意的是此时解析HTML标签与解析CSS是并行执行的。<script>标签后,浏览器会立即开始解析脚本,并停止解析文档,因为脚本有可能会改动DOM与CSS,继续解析会浪费资源,所以应当将<script>标签放于<body></body>后。DOM Tree与CSSOM生成后,将两者结合进行布局,计算它们的大小位置等布局信息,形成一个能够表示这所有信息的内部表示模型,可称为渲染树render tree。paint方法,将内容显示在屏幕上。在浏览器解析DOM结构的过程中是存在阻塞过程的:
JavaScript过程中会阻塞浏览器的解析过程,准确来说解析渲染过程与解析JavaScript的过程是互斥的。CSS加载解析时不会阻塞DOM树的解析过程,这两个解析过程是可以并行的,但是CSS加载过程中是不能进行JavaScript的解析的,也就是说CSS加载过程中是会阻塞JavaScript的解析,此外因为生成Render Tree时需要CSSOM,所以在DOM Tree解析完成而CSSOM未完成时不会继续生成Render Tree。HTML结构同样不会阻塞CSS解析的过程,也同样不会和JavaScript的解析过程并行执行,并且DOM Tree解析未完成而CSSOM完成时同样不会继续生成Render Tree。<script>标签是不会阻塞DOM解析的,当然其就不会阻塞DOMContentLoaded事件的触发,但是依旧会阻塞load事件的触发。再来看一下DOMContentLoaded事件与load事件的触发时机:
HTML文档被完全加载和解析完成之后,DOMContentLoaded事件被触发,而无需等待样式表、图像和子框架的完全加载。关于触发的时机,如果文档中全部为HTML与CSS则DomContentLoaded事件无需等到CSS加载完毕即可触发;当Js都在CSS之前DomContentLoaded事件无需等到CSS加载完毕即可触发,当然解析CSS与DOM是需要等待前边的Js解析完毕的;当Js在CSS之后时,则DomContentLoaded事件需等到CSS与Js加载完毕才能够触发,上文也提到了CSS的加载会阻塞Js的加载,而Js标签本身也属于DOM结构,必须等待其加载完成之后才能触发DomContentLoaded事件;异步加载的<script>标签不会阻塞DOMContentLoaded事件。load事件。不使用动态加载的<iframe>同样会阻塞load事件,此外即使是异步加载的<script>标签同样会阻塞load事件。在各种条件下重新整理一下页面加载的过程,主要是在于DOMContentLoaded事件与load事件触发的时间线:
HTML标签,生成DOM Tree,此时document.readyState = "loading"。<link>或者<style>标签时,开始解析CSS,生成CSSOM,值的注意的是此时解析HTML标签与解析CSS是并行执行的。<script>的时候,阻塞文档解析,等待Js脚本加载并且执行完成后,才会继续解析文档。<script>的时候不阻塞解析文档,继续向下解析,defer属性会使Js文件等待DOM Tree构建完成之后再执行,而async属性会使Js文件在下载完成后立即执行。src创建加载线程,异步加载图片资源,不阻塞解析文档,当然浏览器对于一个域名能够开启最大的线程数量会有限制。document.readyState = "interactive"。defer属性的<script>脚本开始按照顺序执行。DOMContentLoaded事件。async属性的<script>以及图片与<iframe>等加载,直至页面完全加载完成。load事件触发,document.readyState = "complete"。有些时候我们希望尽快介入对DOM的干涉,此时调用DOMContentLoaded事件显然更加合适,而为了处理各种浏览器,需要对其进行兼容处理。
DOMContentLoaded的浏览器使用DOMContentLoaded事件。525版本的Webkit则通过轮询document.readyState来实现。IE浏览器使用Diego Perini发现的著名hack。