Fork me on GitHub

jquery dom ready, jqery2.1.1实现-源码分析

本文链接http://www.cnblogs.com/Bond/p/4178311.html

jquery document  ready的实现其很很简,虽说简单,其很很多人还是没去关注过它的实现。我现在闲来无事就闲扯一下jquery document  ready的实现。在低版本1.XX的实现和2.XX的略有不同,这里以2.1.1为准

平时一般都会这样写,一般就这两种方式 

$(document).ready(function(){
    //do something
})
$(function(){
    //do something
})

分析源码发现其实以上两种写法是一样的效果,所以推荐使用第二组写法,更为简洁。

 

发现最后都是$(document).ready(),为了找到实现,我们就要找到JQuery.fn.ready的实现,于是我们找到了这小段

不难发现最后都是调用了jQuery.ready.promise().done( fn ); 

显然这里得找到jQuery.ready.promise,其实jQuery.ready.promise()返回了一个promise对象然后done(fn) 其实就是向里面添加回调函数,最终也是调用的Callback的add, 

根据上面的推测我们找到了一下这段代码实现

调用jQuery.ready.promise(),进入函数判断readyList是否已经存在,不存在就创建一个deferred对象赋给readyList,此时readyList就是一个Deferred实例对象

往下判断document.readyState === "complete"  如果未true 就执行setTimeout( jQuery.ready ); 稍后分析jQuery.ready这个挂在到JQuery上的静态方法

 

下面就是给document 和window分别添加相应的事件和回调,由于这里只支持高级浏览器,所以简化了很多只有两句话 

document.addEventListener( "DOMContentLoaded", completed, false );

window.addEventListener( "load", completed, false );

 

最终返回return readyList.promise( obj ),所有的DOM ready 的回调都添加到了readyList上面; 这里依赖了JQuery Deferred模块,JQuery Deferred又依赖于Callback. 有兴趣可以去看看它们的实现,还是很有技巧性的,值得一看,这里就不扯那个,一扯就停不下来了。

其实就是返回deferred.promise(obj) ,通过 deferred.promise() 方法返回的 deferred promise 对象,是没有 resolve ,reject, progress , resolveWith, rejectWith , progressWith 这些可以改变状态的方法,你只能使用 done, then ,fail 等方法添加 handler 或者判断状态。

 

这里我们发现最终当DOMContentLoaded 会执行completed 其实completed 最后也是执行jQuery.ready();

最后我们只需要扒开jQuery.ready神秘的面纱,dom ready的最后的实现就迎刃而解了。

于是我们又找到了这段代码

以下简单分析一下它的实现

前面直接调用jQuery.ready(),进入这个函数后第一个判断为false,往下走jQuery.isReady = true; 标记isReady =true, 第二个if也直接跳过,最后执行readyList.resolveWith( document, [ jQuery ] );

这句话是最后的核心,readyList之前被赋值为了Deferred对象的一个实例,这里执行resolveWith() 这里简单说下,resolveWith内部其实就是 jQuery.Callbacks("once memory"),然后resolveWith就是fireWith

知道最后调用的上下文和参数,最终执行之前添加到readyList里面的所有回调。

readyList内部的 

[ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
[ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],

 [ "notify", "progress", jQuery.Callbacks("memory") ]

其它的都忽略 只关注这个jQuery.Callbacks("once memory") 

 我们所有的$(fn) fn都是加到了 jQuery.Callbacks("once memory") 里面,一旦执行过一次fire第二次调用fire就不会有作用,如果调用过fire在add(fn) 这个fn会立即执行。

所以:document ready只会执行一次,一旦执行过在再次$(fn)此时 fn会立即执行。

 

 一个简单的document ready jqeury的实现还是比较绕的,内部依赖了Deferred, 不清楚Deferred的人看来会感觉晕晕的,其实我们可以抛开Deferred 再来看就会觉得简单许多。

 

posted @ 2014-12-22 15:31  xj3614  阅读(488)  评论(0编辑  收藏  举报