您的位置:首页 > Web前端 > JQuery

jQuery源码阅读(九)---ready函数理解

2017-07-17 21:24 477 查看
在jQuery对象创建的时候,即init函数中,有处理这么一种参数情况,当selector为函数时,
$(function(){ })
表示跟
$(document).ready(function(){  })
是一样的情况。

源码是这样的:

if(jQuery.isFunction(selector))
{
//rootjQuery = $(document);
return rootjQuery.ready(selector);
//相当于调$(document).ready()方法。
}


$.fn.ready

上面的
$(document).ready()
相当于调jQuery的实例方法。我们来看看实例方法ready()的源码:

ready: function(fn){
jQuery.bindReady();
readyList.add(fn);
return this;
}


代码只有短短三行,下来一个一个看调用的函数。

bindReady
函数相当于监听文档加载完成的函数,即添加事件处理程序。

bindReady: function(){
//文档的状态主要有五种情况:
//UnInitialized:未开始加载
//Loading:加载程序进行中,但是文件还没有被解析;
//Loaded:部分文件加载并解析,但是文档对象模型(DOM)还暂未生效
//Interactive:只对已加载的文件有效且DOM有效但是只读;
//Complete: 文件已全部加载,表示加载成功。
if ( document.readyState === "complete" ) {
return setTimeout( jQuery.ready, 1 );      //处理IE的问题,它会提前触发ready,所以延迟一下
}
if ( document.addEventListener ) {
//添加事件处理程序,监听DOMContentLoaded事件
document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
//为什么还要监听load事件?因为load事件是可以缓存的,有缓存的话,会先触发load事件
window.addEventListener( "load", jQuery.ready, false );
} else if ( document.attachEvent ) {
//IE事件处理函数
document.attachEvent( "onreadystatechange", DOMContentLoaded );
window.attachEvent( "onload", jQuery.ready );

// 后面这部分暂时没大看懂
var toplevel = false;
try {
toplevel = window.frameElement == null;
} catch(e) {}

if ( document.documentElement.doScroll && toplevel ) {
doScrollCheck();
}
}
}


上面的DOMContentLoaded事件处理函数如下:

if ( document.addEventListener ) {
DOMContentLoaded = function() {
document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
jQuery.ready();
};

} else if ( document.attachEvent ) {
DOMContentLoaded = function() {
// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
if ( document.readyState === "complete" ) {
document.detachEvent( "onreadystatechange", DOMContentLoaded );
jQuery.ready();
}
};
}


可以看到,上面不论是哪种情况分支,都会最终调jQuery.ready()方法。也就是当文档加载完成时,总是会触发
jQuery.ready
函数

ready: function( wait ) {
//表示延迟事件处理函数,其中jQuery.readywait是由jQuery.holdReady函数控制的。
if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {
if ( !document.body ) {
return setTimeout( jQuery.ready, 1 );
}

//表示DOM加载完成,并记录下状态
jQuery.isReady = true;

if ( wait !== true && --jQuery.readyWait > 0 ) {
return;
}

//执行回调函数,这部分函数是在底层模块的回调部分实现的,后面看到的时候再梳理。
readyList.fireWith( document, [ jQuery ] );

//触发ready函数
//考虑到这种用法:$(document).on('ready', function(){})
if ( jQuery.fn.trigger ) {
jQuery( document ).trigger( "ready" ).off( "ready" );
}
}
}


以上是Ready部分的整体实现。下来再做一个简单的梳理:

$(function(){
console.log("Ready");
})


相当于调用
$(document).ready(function(){ console.log("Ready") })


而里面的回调函数
function(){ console.log("Ready") }
是在页面加载完成之后触发,所以按照我们之前事件的思路,要先监听事件,添加事件处理函数,然后在事件被触发的时候才能去执行回调函数。而Ready的源码也是这种思路。

首先
bindReady
函数监听文档加载完成事件,并定义事件处理函数
complete


同时将回调函数加入到ReadyList中,这个是为了管理多个回调函数。因为jQuery中可以多次使用
$(function(){  })


下来就是当页面加载成功时,调用jQuery.ready() 函数,去分别将ReadyList中的回调函数触发,这部分调的是
ReadyList.fireWith()
方法,这个到后面看回调模块时会再整理。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  jquery 源码