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

在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() 方法,这个到后面看回调模块时会再整理。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值