$.queue : 顯示或操作匹配的元素上已經(jīng)執(zhí)行的函數(shù)列隊
這個方法有兩個作用,它既是 setter,又是 getter。第一個參數(shù) elem 是 DOM 元素,第二個參數(shù) type 是字符串,第三個參數(shù) data 可以是 function 或數(shù)組。
var body = $('body');
function cb1() {alert(1)}
function cb2() {alert(2)}
//set,第三個參數(shù)是函數(shù)
$.queue(body, 'aa', cb1);
$.queue(body, 'aa', cb2);
//get
$.queue(body, 'aa') //[function ,function]
這個方法有點類型 get 有點類似隊列的 push 操作,jQuery 的方法的接口重載是非常嚴重的,經(jīng)常同一個接口即是 set 也是 get,不管符不符合基本原則,但是它卻很實用。無非就是把數(shù)據(jù)給緩存起來,為什么載體是一個jQuery對象,因為保存數(shù)據(jù)的手段是通過data數(shù)據(jù)緩存實現(xiàn)的。
queue: function(elem, type, data) {
//參考右邊實現(xiàn)
}
data 與 jQuery 對象之間是通過 uuid 建立了一個無耦合的映射關系,具體可以翻閱之前的關于“數(shù)據(jù)緩存”,源碼有一個默認處理 type = (type || "fx") + "queue" 可見是專職供fx動畫隊列處理的。
$.dequeue : 匹配的元素上執(zhí)行隊列中的下一個函數(shù)
var body = $('body');
function cb1() {console.log(11111)}
function cb2() {console.log(22222)}
//set
$.queue(body, 'aa', cb1); // 第三個參數(shù)為function
$.queue(body, 'aa', cb2);
$.dequeue(body, 'aa') //11
$.dequeue(body, 'aa') //22
出列就有點類似 shift 的操作,但是不同的是還會執(zhí)行這個 cb1 與 cb2,將回調(diào)函數(shù)出列執(zhí)行,每調(diào)用一次僅出列一個,因此當回調(diào)有 N 個時,需要調(diào)用 $.dequeue 方法 N 次元素才全部出列,來看看源碼:
var dequeue = jQuery.queue(elem, type),
//參考右邊實現(xiàn)
};
知道原理了, 這個就很簡單了,通過 queue 的 get 取出隊列的所有數(shù)據(jù),判斷一下長度,然后截取出第一個,然后做好一個預處理生成下一個的 next。
這里有一個hooks?
仔細分析下這個內(nèi)部 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不僅是取出來還需要執(zhí)行,在執(zhí)行的時候把next與hooks傳遞給外部的回調(diào),這就是js的邏輯上的很繞的地方,在內(nèi)部可以傳遞一個引用出去,又能提供外部調(diào)用或者執(zhí)行。
fn.call(elem, next, hooks)
因為傳遞了next,所以我們的代碼可以參考右邊代碼,next內(nèi)部仍然調(diào)用$.dequeue,這樣可以接著執(zhí)行隊列中的下一個 callback,$.dequeue 里的 hooks 是當隊列里所有的 callback 都執(zhí)行完后(此時 startLength 為0)進行最后的一個清理工作。
if ( !startLength && hooks ) {
hooks.empty.fire();
}
鉤子其實就是 jQuery.Callbacks 對象,可以實現(xiàn)一個收集器的功能,至于在什么情況下時候,之后動畫中開始分析,所以隊列的本質(zhì)是利用 Array 的 push 和 shift 來完成先進先出(First In First Out),但是這個方法的缺點也很明顯,無法單獨做一個獨立的模塊處理,因為它必須要跟 jQuery 對象吻合,而且對傳遞的數(shù)據(jù)只能是函數(shù)。