$.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 對象吻合,而且對傳遞的數據只能是函數。