jQuery源码解析(3)—— ready加载、queue队列

本文详细解析jQuery库中ready事件和queue队列的实现原理。ready事件确保DOM加载完成后再执行回调,queue则用于管理异步调用的函数序列,特别是在动画效果中。文章介绍了jQuery如何利用DOMContentLoaded、readystatechange和load事件监听DOM加载,并通过 Deferred 对象处理 ready 事件。同时,详述了queue的内部结构和API,包括如何添加、执行和管理队列。
摘要由CSDN通过智能技术生成

ready、queue放在一块写,没有特殊的意思,只是相对来说它俩可能源码是最简单的了。ready是在dom加载完成后,以最快速度触发,很实用。queue是队列,比如动画的顺序触发就是通过默认队列’fx’处理的。

(本文采用 1.12.0 版本进行讲解,用 #number 来标注行号)

ready

很多时候,我们需要尽快的加载一个函数,如果里面含有操作dom的逻辑,那么最好在dom刚刚加载完成时调用。window的load事件会在页面中的一切都加载完毕时(图像、js文件、css文件、iframe等外部资源)触发,可能会因外部资源过多而过迟触发。

DOMContentLoaded:IE9+、Firefox、Chrome、Safari3.1+、Opera9+
html5规范指定的标准事件,在document上,在形成完整的dom树后就会触发(不理会图像、js文件、css文件等是否下载完毕)。

readystatechange:IE、Firfox4+、Opera
这个事件的目的是提供与文档或元素的加载状态相关的信息,但这个事件的行为有时候很难预料。支持该事件的每个对象都有一个readyState属性,可能包含下列5个值中的一个。

uninitialized(未初始化):对象存在但尚未初始化
loading(正在加载):对象加载数据完成
interactive(交互):可以操作对象了,但还没有完全加载
complete(完成):对象已经加载完成

对document而言,值为”interactive”的readyState会在与DOMContentLoaded大致相同时刻触发readystatechange(行为难料,该阶段既可能早于也可能晚于complete阶段,jq上报告了一个interactive的bug,所以源码中用的complete)。而且在包含较少或较小的外部资源的页面中,readystatechange有可能晚于load事件,因此优先使用DOMContentLoaded

jQuery思路

jq可以通过$(xx).ready(fn)指定dom加载完后需要尽快调用的事件。我们知道事件一旦错过了监听,就不会再触发,$().ready()增加了递延支持,这里自然要使用'once memory'的观察者模型,Callback、Deferred对象均可,源码中是一个Deferred对象,同时挂载在变量readyList上。

// #3539
jQuery.fn.ready = function( fn ) {
   

    // jQuery.ready.promise() 为deferred对象内的promise对象(即readyList.promise())
    jQuery.ready.promise().done( fn );

    // 链式
    return this;
};

有了promise对象,需要dom加载完后,尽快的resolve这个promise。判断加载完的方式,就是首先判断是否已经是加载完成状态,如果不是优先使用DOMContentLoaded事件,IE6-8用readystatechange,都要用load事件保底,保证一定触发。由于readystatechange为complete时机诡异有时甚至慢于load,IE低版本可以用定时器反复document.documentElement.doScroll('left')判断,只有dom加载完成调用该方法才不报错,从而实现尽快的触发。

jQuery是富有极客精神的,绑定的触发函数调用一次后就不再有用,因此触发函数中不仅能resolve那个promise,还会自动解绑触发函数(方法detach()),这样比如readystatechange、load多事件不会重复触发,同时节省内存。当然doScroll方法是setTimeout完成的,如果被readystatechange抢先触发,需要有变量能告知他取消操作,源码中是jQuery.isReady
触发函数->completed() = 解绑触发函数->detach() + resolve那个promise->jQuery.ready()

jq中增加了holdReady(true)功能,能够延缓promise的触发,holdReady()不带参数(即jQuery.ready(true))则消减延迟次数,readyWait初始为1,减至0触发。由于doScroll靠jQuery.isReady防止重复触发,因此即使暂缓jQuery.ready()也要能正常的设置jQuery.isReady = true。jQuery.ready()不仅能触发promise,之后还会触发’ready’自定义事件。

思路整理

jQuery.fn.ready()  -> 供外部使用,向promise上绑定待执行函数
jQuery.ready.promise()  -> 生成单例promise,绑定事件触发completed()
complete()  -> 解绑触发函数`detach()` + 无需等待时resolve那个promise`jQuery.ready()`

[源码]

// #3536
// readyList.promise() === jQuery.ready.promise()
var readyList;

jQuery.fn.ready = function( fn ) {
   

    // promise后添加回调
    jQuery.ready.promise().done( fn );
    return this;    // 链式
};

jQuery.extend( {

    // doScroll需借此判断防止重复触发
    isReady: false,

    // 需要几次jQuery.ready()调用,才会触发promise和自定义ready事件
    readyWait: 1,

    holdReady: function( hold ) {
   
        if ( hold ) {
            // 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值