js便签笔记(6)——jQuery中的ready()事件为何需要那么多代码?
2014-04-13 22:06
671 查看
前言:
ready()事件的应用,是大家再熟悉不过的了,学jQuery的第一步,最最常见的代码:jQuery(document).ready(function () { }); jQuery(function () { }); $(document).ready(function () { }); $(function () { });
以上四行代码的目的和效果都一样——待DOM加载完成之后,执行传入的function函数。
再对jquery稍微熟悉一点的朋友可能知道,这里的“待DOM加载完成”,不是window.onload事件,window.onload是指“DOM加载完成 + DOM相关的文件下载完成”。这里的“DOM加载完成”,不包括“DOM相关的文件加载完成”。相关的事件是:
DOMContentLoaded事件(IE9+以及其他浏览器)
onreadystatechange事件(IE9以下浏览器)
问题就在这里。如果知道了这两个事件,那么把传入的function函数关联到这两个事件上就行了,而jquery中与ready相关的代码洋洋洒洒的写了那么多,至于上百行代码。这是为何?
原因在于以下几点:
2. 存储结构——基于异步队列设计:
先看以下代码://应用ready事件 $(function () { alert(10); }); $(function () { alert(20); }); $(function () { alert(30); });
以上代码连续应用了三次ready方法,其实jquery是用本身的jquery.callbacks来处理的。主要代码如下:
readyList = jQuery.Callbacks( "once memory" ); readyList.add( fn ); readyList.fireWith( document, [ jQuery ] );
"once":代表add进来的函数只被调用一次;
"memory":代表一旦readylist被执行过一次,那么它后续添加进来的函数会立即按照执行时候的环境和参数执行。
3. 巧妙的事件绑定:
以IE9+和其他浏览器支持的DOMContentLoaded为例。先看代码:// Mozilla, Opera and webkit nightlies currently support this event if ( document.addEventListener ) { // Use the handy event callback document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); // A fallback to window.onload, that will always work window.addEventListener( "load", jQuery.ready, false ); } DOMContentLoaded = function() { document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); jQuery.ready(); };
根据以上代码可见,最终DOMContented事件执行的,其实是jQUery.ready()这个工具函数。(注意,jquery.ready()和jquery(document).raedy()不一样!!,前者是工具函数,后者是实例函数。)
这里是通过定义一个DOMContentLoaded函数作为桥梁来执行jquery.ready()函数的,这样做的目的就是为了即使的remove掉document的DOMContentLoaded事件的引用。
document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
单独把这两行摘出来,可以看明白,add完了之后,接着remove掉了,在这中间,巧妙的执行了jquery.ready(),这种用法值得学习!
反过来,如果像以下代码那么样实现,document的DOMContentLoaded事件的引用将无法及时删除。
//反例 document.removeEventListener( "DOMContentLoaded", jQuery.ready, false );
另外,除了通过浏览器的DOMContentLoaded/onreadystatechange方法可以调用jquery.ready()函数之外,还有一种巧妙的方式调用jquery.ready()函数。
在IE9以下的浏览器中,如果当前页面是顶层(即没有包含在iframe和friame元素中),调用html.doScroll(),直到不抛出异常,即可调用jquery.ready()函数。
if ( document.documentElement.doScroll && toplevel ) { doScrollCheck(); } /*省略*/ try { // If IE is used, use the trick by Diego Perini // http://javascript.nwbox.com/IEContentLoaded/ document.documentElement.doScroll("left"); } catch(e) { setTimeout( doScrollCheck, 1 ); return; } // and execute any waiting functions jQuery.ready();
4. 事件执行:
上文中讲到,可以通过浏览器的DOMContentLoaded/onreadystatechange事件,以及对html.doScroll()的检测来调用jquery.ready()工具函数,jquery.ready()最终将会调用异步队列的firewith()方法触发传入的所有事件。如果是通过js手动调用,也可以通过jquery事件系统来调用。readyList.fireWith( document, [ jQuery ] ); if ( jQuery.fn.trigger ) { jQuery( document ).trigger( "ready" ).off( "ready" ); }
其实这其中还有个jquery.holdready()方法用来延迟调用,不过比较简单,也不常用,此处不说了。
5. 总结:
可见,jQuery中的ready()事件并不是我们看起来那么简单,了解其原理的同时,也应该想想我们在自己设计系统的时候,考虑的时候全面。它用到了异步队列,使得使用者可以多次调用,顺序执行;
它的事件绑定考虑到了各种情况,而又充分考虑了资源的释放;
它同时考虑了浏览器调用的情况,和js手动调用的情况。
个人感受:想了解js到底该怎么用,了解js的源码和设计,是一个捷径。
相关文章推荐
- js便签笔记(5)——Dean Edwards大牛的跨浏览器AddEvent()设计(不知道是不是jQuery事件系统的原型)
- 使用JS或jQuery模拟鼠标点击a标签事件代码
- js和jquery实现监听键盘事件示例代码
- 模拟jQuery中的ready方法及实现按需加载css,js实例代码
- JavaScript之事件委托(附原生js和jQuery代码)
- 使用JS或jQuery模拟鼠标点击a标签事件代码
- 使用JS或jQuery模拟鼠标点击a标签事件代码
- js---如何通过js/jQuery代码出发节点的click事件
- jQuery的ready()事件与js中的onload事件的区别
- 关于js的核心笔记--需要注意的地方都在这里啦,有测试代码
- 史上最全的CSS hack方式一览 jQuery 图片轮播的代码分离 JQuery中的动画 C#中Trim()、TrimStart()、TrimEnd()的用法 marquee 标签的使用详情 js鼠标事件 js添加遮罩层 页面上通过地址栏传值时出现乱码的两种解决方法 ref和out的区别在c#中 总结
- js和jquery实现监听键盘事件示例代码
- jQuery的ready()事件与js中的onload事件的区别
- 使用JS或jQuery模拟鼠标点击a标签事件代码
- jQuery 中 $(document).ready()事件与js中window.onload()事件的区别
- js便签笔记(9)——解读jquery源码时记录的一些知识点
- JS和JQuery中的事件委托 学习笔记
- 【JavaScript】jquery右键点击事件和js禁用右键事件代码
- JS和JQuery中的事件托付 学习笔记
- js和jquery实现监听键盘事件示例代码