js便签笔记(6)——jQuery中的ready()事件为何需要那么多代码?
前言:
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便签笔记(6)——jQuery中的ready()事件为何需要那么多代码?的更多相关文章
- js便签笔记(2)——DOM元素的特性(Attribute)和属性(Property)
1.介绍: 上篇js便签笔记http://www.cnblogs.com/wangfupeng1988/p/3626300.html最后提到了dom元素的Attribute和Property,本文简单 ...
- js便签笔记(12)——浏览TOM大叔博客的学习笔记 part2
1. 前言 昨天写了<js便签笔记(11)——浏览TOM大叔博客的学习笔记 part1>,简单记录了几个问题.part1的重点还是在于最后那个循环创建函数的问题,也就是多个子函数公用一个闭 ...
- js便签笔记(13)——jsonp事实上非常easy【ajax跨域请求】
前两天被问到ajax跨域怎样解决,还真被问住了,光知道有个什么jsonp,迷迷糊糊的没有说上来.抱着有问题必须解决的态度,我看了很多资料,原来如此.. . 为何一直知道jsonp,但一直迷迷糊糊的不明 ...
- js便签笔记(9)——解读jquery源码时记录的一些知识点
近来一直利用业余时间在看jquery2.1.1源码,大约看了两千行了.平时看的时候,做了一些笔记,贴出来分享. 1. Array.prototype.slice.call 可以将伪数组转化为真正的数组 ...
- js便签笔记(5)——Dean Edwards大牛的跨浏览器AddEvent()设计(不知道是不是jQuery事件系统的原型)
1. 前言: 在看Aaron的jquery源码解读时候,看到事件系统那块,作者提到了Dean Edwards的添加事件的设计,于是就点进去看了看.首先让我吃惊的是,代码非常少,寥寥几十行,非常简单.于 ...
- js便签笔记(13)——jsonp其实很简单【ajax跨域请求】
前两天被问到ajax跨域如何解决,还真被问住了,光知道有个什么jsonp,迷迷糊糊的没有说上来.抱着有问题必须解决的态度,我看了许多资料,原来如此... 为何一直知道jsonp,但一直迷迷糊糊的不明白 ...
- js便签笔记(11)——浏览TOM大叔博客的学习笔记 part1
1. 前言 这两天看了一下TOM大叔的<深入理解js系列>中的基础部分,根据自己的实际情况,做了读书笔记,记录了部分容易绊脚的问题.写篇文章,供大家分享. 2. 关于HTMLCollect ...
- js便签笔记(10) - 分享:json2.js源码解读笔记
1. 如何理解“json” 首先应该意识到,json是一种数据转换格式,既然是个“格式”,就是个抽象的东西.它不是js对象,也不是字符串,它只是一种格式,一种规定而已. 这个格式规定了如何将js对象转 ...
- js便签笔记(10) - 分享:json.js源码解读笔记
1. 如何理解“json” 首先应该意识到,json是一种数据转换格式,既然是个“格式”,就是个抽象的东西.它不是js对象,也不是字符串,它只是一种格式,一种规定而已. 这个格式规定了如何将js对象转 ...
随机推荐
- 【笔记】CSS选择器整理(IE低版本支持性测试)
时间:2015.05.11 参考附件:css选择器.xmind(网友共享) 查看链接:http://www.w3school.com.cn/cssref/css_selectors.asp htt ...
- Java理论学时第一节。课后作业。
设计思路:用nextFloat()函数将从键盘输入的值分别赋给多个变量,然后直接输出相加结果. 流程图: 源代码: 实验结果:
- java基础-day17
第06天 集合 今日内容介绍 u 集合&迭代器 u 增强for & 泛型 u 常见数据结构 u List子体系 第1章 集合&迭代器 1.1 集合体系结构 1.1 ...
- limit
在我们使用查询语句的时候,经常要返回前几条或者中间某几行数据,这个时候怎么办呢?不用担心,mysql已经为我们提供了这样一个功能. SELECT * FROM table LIMIT [offset ...
- 数据压缩之经典——哈夫曼编码(Huffman)
(笔记图片截图自课程Image and video processing: From Mars to Hollywood with a stop at the hospital的教学视频,使用时请注意 ...
- hdu 5051 找规律?+大trick
http://acm.hdu.edu.cn/showproblem.php?pid=5051 打表找规律 据说是http://zh.wikipedia.org/wiki/%E6%9C%AC%E7%A6 ...
- 第K大01背包
其实这个问题,真的挺好想的,但是我咋想了那么久呢~~ 很好理解,第K大01背包一定基于01背包,dp数组也很容易的想到由dp[V] ----> dp[V][K],来表示背包容量是V时候的第 ...
- SRM466
250pt: 给出一个数n(n <= 10^10),问至少修改几位能使其变成完全平方数. 思路: 直接枚举平方根,然后统计. 注意枚举时要枚举到比她大.. #line 7 &qu ...
- HDU 1465 2045 已知结果往前推
1465 不容易系列之一 Time Limit: 1000 MS Memory Limit: 32768 KB 64-bit integer IO format: %I64d , %I64u Java ...
- CxGrid筛选自动添加百分号和默认旧的滚动条样式
CxGrid筛选自动添加百分号和默认旧的滚动条样式 2018-10-29 Delphi 约 693 字 预计阅读 2 分钟 文章目录 cxGrid支持使用like过滤时自动添加百分号 DevExpr ...