$.queue : 显示或操作匹配的元素上已经执行的函数列队
这个方法有两个作用,它既是 setter,又是 getter。第一个参数 elem 是 DOM 元素,第二个参数 type 是字符串,第三个参数 data 可以是 function 或数组。
var body = $('body');
function cb1() {alert(1)}
function cb2() {alert(2)}
//set,第三个参数是函数
$.queue(body, 'aa', cb1);
$.queue(body, 'aa', cb2);
//get
$.queue(body, 'aa') //[function ,function]
这个方法有点类型 get 有点类似队列的 push 操作,jQuery 的方法的接口重载是非常严重的,经常同一个接口即是 set 也是 get,不管符不符合基本原则,但是它却很实用。无非就是把数据给缓存起来,为什么载体是一个jQuery对象,因为保存数据的手段是通过data数据缓存实现的。
queue: function(elem, type, data) {
//参考右边实现
}
data 与 jQuery 对象之间是通过 uuid 建立了一个无耦合的映射关系,具体可以翻阅之前的关于“数据缓存”,源码有一个默认处理 type = (type || "fx") + "queue" 可见是专职供fx动画队列处理的。
$.dequeue : 匹配的元素上执行队列中的下一个函数
var body = $('body');
function cb1() {console.log(11111)}
function cb2() {console.log(22222)}
//set
$.queue(body, 'aa', cb1); // 第三个参数为function
$.queue(body, 'aa', cb2);
$.dequeue(body, 'aa') //11
$.dequeue(body, 'aa') //22
出列就有点类似 shift 的操作,但是不同的是还会执行这个 cb1 与 cb2,将回调函数出列执行,每调用一次仅出列一个,因此当回调有 N 个时,需要调用 $.dequeue 方法 N 次元素才全部出列,来看看源码:
var dequeue = jQuery.queue(elem, type),
//参考右边实现
};
知道原理了, 这个就很简单了,通过 queue 的 get 取出队列的所有数据,判断一下长度,然后截取出第一个,然后做好一个预处理生成下一个的 next。
这里有一个hooks?
仔细分析下这个内部 queueHooks
_queueHooks: function(elem, type) {
var key = type + "queueHooks";
return data_priv.get(elem, key) || data_priv.access(elem, key, {
empty: jQuery.Callbacks("once memory").add(function() {
data_priv.remove(elem, [type + "queue", key]);
})
});
}
我们说了dequeue不仅是取出来还需要执行,在执行的时候把next与hooks传递给外部的回调,这就是js的逻辑上的很绕的地方,在内部可以传递一个引用出去,又能提供外部调用或者执行。
fn.call(elem, next, hooks)
因为传递了next,所以我们的代码可以参考右边代码,next内部仍然调用$.dequeue,这样可以接着执行队列中的下一个 callback,$.dequeue 里的 hooks 是当队列里所有的 callback 都执行完后(此时 startLength 为0)进行最后的一个清理工作。
if ( !startLength && hooks ) {
hooks.empty.fire();
}
钩子其实就是 jQuery.Callbacks 对象,可以实现一个收集器的功能,至于在什么情况下时候,之后动画中开始分析,所以队列的本质是利用 Array 的 push 和 shift 来完成先进先出(First In First Out),但是这个方法的缺点也很明显,无法单独做一个独立的模块处理,因为它必须要跟 jQuery 对象吻合,而且对传递的数据只能是函数。