兼容所有浏览器的 DOM 载入事件

标签: Chrome DOM HTML JavaScript jQuery | 发表时间:2016-05-14 00:00 | 作者:Harttle
出处:http://harttle.com/

本文就页面载入问题讨论 DOMContentLoadedloadreadyState等DOM事件的浏览器兼容性, 并给出怎样绑定DOM载入事件以兼容所有的浏览器。 接着介绍jQuery对该问题的实现源码,以及jQuery中 $(document).ready()$(window).load()方法的区别。

在讨论页面载入事件之前,首先需要区分的两个概念:DOM就绪和渲染结束。

  • DOM就绪是指浏览器已经接收到整个HTML并且DOM解析完成;
  • 渲染结束是指浏览器已经接收到HTML中引用的所有样式文件、图片文件、以及Iframe等资源并渲染结束。

DOM API 提供的事件

DOM API 在页面载入问题上主要提供了三个接口:

  • DOMContentLoaded事件;
  • load事件;
  • document.readyState属性,及其对应的 readystatechange事件。

我们看看这三者有什么区别:

DOMContentLoaded

   document.addEventListener("DOMContentLoaded", function(event) {
    console.log("DOM ready!");
});

页面文档(DOM)完全加载并解析完毕之后,会触发 DOMContentLoaded事件, HTML文档不会等待样式文件,图片文件,Iframe页面的加载。 此时DOM元素可能还未渲染结束,位置大小等状态可能不正确, 但DOM树已被创建,多数JavaScript已经操作DOM并完成功能了。 所以绝大多数场景下都应当使用 DOMContentLoaded事件, jQuery也采用了这种实现。

This (DOMContentLoaded) event fires after the HTML code has been fully retrieved from the server, the complete DOM tree has been created and scripts have access to all elements via the DOM API. – molily.de

其实样式文件的加载会阻塞后续脚本执行, 此时多数浏览器都会推迟 DOMContentLoaded事件的触发, 在 样式表的载入会延迟DOM载入事件一文中详细地讨论了这一点。

考虑到IE8及以下不支持该事件,因此我们需要后面的两个 DOM 事件作为Fallback。

load

   document.addEventListener("load", function(event) {
    console.log("All resources finished loading!");
});

页面完全载入时触发 load事件,此时所有的图片等资源文件都已完全接收并完成渲染。 因此 load总是在 DOMContentLoaded之后触发。 load事件没有任何兼容性问题。 load常常被作为最终的Fallback。

注意IE8及以下不支持 addEventListener,需要使用 attachEvent来绑定事件处理函数。 详见: DOM 事件与 jQuery 源码:捕获与冒泡一文。

document.readyState

document.readyState属性用来表征DOM的加载状态, 该属性值发生变化时会触发 redystatechange事件。 document.readyState属性有三种取值:

  • "loading":DOM在加载过程中;
  • "interactive":DOM就绪但资源仍在加载中;
  • "complete":DOM加载完成。

由于IE8支持 document.readyState属性,也常常用来在IE8中作为 DOMContentLoaded的Fallback。

注意IE8以前的IE不支持 document.readyState属性。 可以执行 document.documentElement.doScroll("left"), 当DOM未就绪时执行该方法会抛出错误,以此检测DOM是否就绪。

jQuery 方法

jQuery提供了三种方法来提供页面载入事件:

  1. $(document).ready(callback):在DOM就绪时执行回调,返回值为 document构成的jQuery集合。
  2. $(function(){}):这是最常用的写法,参数与返回值同上。
  3. $(window).load():DOM就绪,并且页面渲染结束(图片等资源已接收完成)时执行回调。

更多jQuery函数 $()的用法请参考 jQuery中$()函数有几种用法一文,本文不再赘述。

上述三个方法在事实上相当于只有两个: .ready().load()

.ready()方法的实现在这里: https://github.com/jquery/jquery/blob/master/src/core/ready.js

   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 );
} else {
    // Use the handy event callback
    document.addEventListener( "DOMContentLoaded", completed );
    // A fallback to window.onload, that will always work
    window.addEventListener( "load", completed );
}

.load()就是DOM load的包装,不再赘述。 DOM 事件与 jQuery 源码:捕获与冒泡一文详述了jQuery如何包装DOM事件。

参考阅读

相关 [浏览器 dom 事件] 推荐:

兼容所有浏览器的 DOM 载入事件

- - Harttle Land
本文就页面载入问题讨论 DOMContentLoaded、 load、 readyState等DOM事件的浏览器兼容性, 并给出怎样绑定DOM载入事件以兼容所有的浏览器. 接着介绍jQuery对该问题的实现源码,以及jQuery中 $(document).ready()和 $(window).load()方法的区别.

细说dom就绪事件

- - 崔永键的博客
OK,现在来谈谈DOM就绪事件. 这个问题,关系到浏览器内核实现,但我们作为前端,能力不及. 便从表象上去理解它,进而推断出对前端开发有所帮助的实践方案,就够了. OK,浏览器DOM加载顺序是什么样的呢. 可以参考IBM的一篇文章:http://www.ibm.com/developerworks/cn/web/1308_caiys_jsload/.

DOM元素在浏览器中的位置参数,如offset,ownerDocument

- - 浏览器 - 互联网 - ITeye博客
学习一下,好像有很多相关的参数. window.pageYOffset:Netscape属性,指的是滚动条顶部到网页顶部的距离. 2,getBoundingClientRect 获取元素位置. 对于文本对象,W3C提供了一个 TextRectangle 对象,这个对象是对文本区域的一个解释. 这里的文本区域只针对inline 元素,比如:a, span, em这类标签元素.

resizable和draggable组件在IE8下浏览器越界无法释放对目标DOM控制的问题

- - WebUI框架使用参考
标题有点长, 不考虑IE8兼容性的朋友可以直接忽视本文,本文所提到的问题是只在IE8这个垃圾版本下才会有的问题. 大家在使用window组件的时候,应该注意到在IE8下,当resize或者拖动window超出浏览器边界的时候,被resize或者拖动的window组件实例依旧处于被reszie或者被拖动的状态,即便是松开鼠标也没有用.

样式表的载入会延迟DOM载入事件

- - Harttle Land
绝大多数情况下我们总是让JavaScript在DOM载入后再开始执行. 不管是直接用 DOM API 实现还是使用 jQuery,最终都是 DOMContentLoaded事件在起作用. 本文讨论一个我们习以为常却很少了解的问题: 样式文件的载入会延迟脚本执行,以及 DOMContentLoaded事件的触发.

浏览器事件的思考

- - 博客 - 伯乐在线
doSomeThing();//这个方法貌似很有名. 上面的代码看起来像是很好的完成了我们交给它的工作, 浏览器不会再将我们重定向到href中的链接,但这么做到底有什么不对呢. 在解释有什么不对前,我们来看看浏览器中事件中的几个概念. 当我们点击某一个链接的时候,浏览器会直接跳转,在表单中按回车,表单会自动提交,这些都是浏览器的默认行为.

跨浏览器resize事件分析

- - CSDN博客Web前端推荐文章
window一次resize事件:. IE7 触发3次, IE8 触发2次, IE9 触发1次, IE10 触发1次. window resize时,部分组件需要重置大小(一次);部分组件不需要重置大小;. 优点:分Debounced和Throttled两种类型,类型明确. 大多数场景使用jquery-smartresize的Debounced即可满足一次调用即可.

DOM事件阶段以及事件捕获与事件冒泡先后执行顺序 - AlvinWei

- - 博客园_首页
平时浏览这么多技术文章,如过不去实践、深入弄透它,这个技术点很快就会在脑海里模糊. 重要的事情说三遍,重要的知识写一遍. 开发过程中我们都希望使用别人成熟的框架,因为站在巨人的肩膀上会使得我们开发的效率大幅度提升. 不过,我们也应该、必须了解其基本原理. 比如DOM事件,jquery框架帮我们为我们封装和抽象了各浏览器的差异行为,为事件处理带来了极大的便利.

DOM详解

- - CSDN博客推荐文章
 1.XML解析方式分为两种:dom和sax.   (1)dom:(Document Object Model, 即文档对象模型) 是 W3C 组织推荐的处理 XML 的一种方式.   (2) sax:(Simple API for XML) 不是官方标准,但它是 XML 社区事实上的标准,几乎所有的 XML 解析器都支持它.

javaScript DOM使用

- - CSDN博客互联网推荐文章
通过 HTML DOM,可访问 JavaScript HTML 文档的所有元素. 1 修改HTML元素内容. document.write(Date()); //在输入流中直接写 document.getElementById(id).innerHTML=new HTML. //改变已经有的元素内容 document.getElementById("image").src="landscape.jpg";.