jQuery ready 方法解析
2013-11-21
不知道多少次同事让我帮忙改东西,问题的原因出在页面dom没有加载完成的时候开始对其进行操作,应对的方法不尽完美:
- 把执行代码放在页面底部
- 使用jQuery的ready方法
如果不想使用jQuery
的时候就只能在页面底部引入或者留下一些代码,让人很不舒服。在网上查阅关于jQuery
中ready
方法的资料,也未得到非常满意的答案,周末在家花了点时间研究了下jQuery(参照1.10.2)
源码中ready
方法的实现,现在讲一下原理。
load事件
我们在熟悉的一个事件便是load
了,几乎所有的浏览器都支持了这个方法。但是load
有一个十分致命缺点:它会等待样式文件、图片文件和子框架页面加载完毕之后才会调用,甚至会因为资源加载的阻塞而不触发这个函数,这样的话这它就变的非常脆弱,及不保险。
DOMContentLoaded事件
另一个事件叫做DOMContentLoaded
,它会在页面文档加载完毕并解析完毕的时候调用,而不会去等待样式图片等文件。这样看来用它就可以实现我们想要的效果了,当然,如果IE同意的话。
Feature | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
Basic support | 0.2 | 1.0 (1.7 or earlier) | 9.0 | 9.0 | 3.1 |
除了IE之外的其它浏览器似乎问题不大,下面的重点就是IE6/7/8的兼容问题。
readystatechange事件
还好IE对这个事件支持的不错。支持readystatechange事件的对象有一个readyState
属性,可能包含以下五个值中的一个:
- uninitialized(未初始化)
- loading(加载中)
- loaded(加载完毕)
- interactive(交互)
- complete(完成)
由于浏览器支持的不同,很难保证这五个参数会何时以何种顺序出现,不过状态complete
一定是在文档交互或者完成时出现。所以只要监听readyState
的状态,在complete
时调用我们的函数即可。
事实上到现在为止,个人非常不严谨的测试中发现已经可以实现ready,不过jQuery中还加了一个方法。
如果没有下面的东西,我可省不少心考证。
doScroll
大多数讲解总是模糊的带过这一段,没有一个说的清清楚楚的。
IE
中的doScroll
方法执行时必须要求文档已经完全加载,不然就会报错,就利用这个,让document.documentElement
一直调用doScroll
直到它不报错的时候,去执行我们的方法,就是所谓的ready
。
在使用时,许多框架中都是先判断是IE并且不是在IFrame里面的时候,才去使用doScroll
。
到这里需要思考两个问题:第一,上面的功能已经可以实现了为什么还在这里使用doScroll
?第二,使用doScroll
的时候为什么还要保证不是在IFrame
里面?
第一个问题还要解释点,如同时绑定readystatechange
和load
两个事件一样,起并行保险作用,而且貌似doScoll
的反应要迅速于前两者。
关于第二个问题几乎没有讲解的,糊糊弄弄的也都说不出什么,我问过一个大牛,他说:
IFrame需要加载远程的资源,会清空dom树,因此使用doScroll不准确。
总结
所以现在ready
就很明了很明了的展示在眼前了:
- 给非
IE
绑定DOMContentLoaded
和load
事件,在触发其中一个的时候,执行ready
,卸载掉所有事件绑定。 - 给
IE
绑定load
和readystatechange
事件,在触发其中一个的时候,作判断,前者直接执行后者判断状态,之后卸载掉所有事件绑定。 - 满足是
IE
并且不在IFrame
中时(是否在IFrame
中可以用window.frameElement
的值来判断),开始不断请求调用doScroll
,在不报错时停止,执行ready
,清除绑定事件。
最后
至于怎样实现多函数添加应该不是什么麻烦事儿了。
实现的写法上就当然各有千秋,找到一个非常棒的,大家可以借鉴一下(From:http://javascript.nwbox.com/ContentLoaded/ ):
1 | /*! |