queue
隊列方法:執行順序的管理。
(1)jQuery用extend擴展,是有工具方法。 jQuery.extend({ queue // 添加 相似數組的push dequeue // 刪除 相似於 shift _queueHooks // 給傳入的數據進行處理,加個 argu+queue。 }); 注意:在 queue 和 dequeue 中存入的必須是一個函數,其餘格式不能夠。
例子:(1)
工具方法使用。
function aaa() {
alert('aaa');
}
function bbb() {
alert('bbb');
}
$.queue(document, 'q1', aaa); // 這裏建立了一個q1的隊列。存入了一個值,是個函數aaa
$.queue(document, 'q1', bbb); // 這裏在去q1隊列中加入了第二個值,是函數bbb
// $.queue(document, 'q1', [aaa, bbb]); //也能夠直接存入一個數組。
console.log( $.queue(document, 'q1') ); // FF 打印出 [aaa(), bbb()]。
// 注意:queue 和 dequeue 中存入的必須是一個函數。
$.dequeue(document, 'q1'); // 彈出 aaa函數 ,出隊,只是把第一個函數取出來。並執行 aaa();
$.dequeue(document, 'q1'); // 彈出 bbb函數 ,出隊,又把第一項給讀取出來。並執行 bbb();
//注意: dequeue,取出第一個變量,並執行它,其餘的類型,沒法執行。
例子:(2)
實例方法使用。
$(document).queue('p1', aaa);
$(document).queue('p1', bbb);
console.log( $.queue(document, 'p1') ); // FF 打印出 [aaa(), bbb()]。
$(document).dequeue('p1', bbb); // 打印 aaa函數。
(2)jQuery.fn.extend 擴展的是實例方法。 jQuery.fn.extend({ queue dequeue delay // 延遲隊列 clearQueue promise }); 思考:隊列的做用。 $('#test').click(function () { $(this).animate({width: 400}, 2000); // (1) $(this).animate({height: 400}, 2000); // (2) $(this).animate({left: 200}, 2000); // (3)這裏position要absolute // 和上面同樣。 // $(this).animate({width: 400}, 2000).animate({height: 400}, 2000).animate({left: 200}, 2000); }); // 這裏的執行順序是一次執行,不是併發執行。(1)-->(2)-->(3) // 用定時器開啓,而後執行。可是定時器是異步操做。setInterval是異步操做。 // 這個就是用隊列實現的。 當使用動做函數的時候,用 queue 依次將其中對函數壓入隊列fx。運行的時候,就 dequeue 操做。 deferred 的是控制一個操做,queue 是控制一系列的操做。 可是 deferred 針對異步操做,延遲對象更強大一些。主要針對的是一個異步操做的控制。 queue是針對多個的。deferred很難完成多異步的操做。 在 jQuery 中 queue 主要針對的是運動的操做,去解決連續運動的這個操做。
例子
A-------------------- 使用規則
$(this).animate({width: 400}, 2000).queue('fx', function () {
$(this).dequeue(); // 若是沒有這個出隊操做,後面的,就沒法繼續執行了。
}).animate({height: 400}, 2000).animate({left: 200}, 2000);
B--------------------- fx能夠省略,而且若是調用函數,須要使用$(this).dequeue();
// 這裏的 fx 是能夠省略的,默認就是。
$(this).animate({width: 400}, 2000).queue(function () {
$(this).dequeue(); // 若是沒有這個出隊操做,後面的,就沒法繼續執行了。
}).animate({height: 400}, 2000).animate({left: 200}, 2000);
C--------------------- 傳入的參數,等價於dequeue。
$(this).animate({width: 400}, 2000).queue(function (next) {
$(this).css('left', 200);
next();
}).animate({height: 400}, 2000).animate({left: 200}, 2000);
D------------- 利用回調函數的形式
$(this).animate({width: 400}, 2000, function () {
$(this).css('left', 200);
}).animate({height: 400}, 2000).animate({left: 200}, 2000);
E-------------------- 能夠經過控制queue,來控制,保證異步的順序。
$(this).animate({width: 400}, 2000).queue(function (next) {
var _this = this;
var timer = setInterval(function () {
_this.style.height = ( _this.offsetHeight + 1 ) + "px";
if (_this.offsetHeight >= 400) {
next(); // 能夠控制出隊的時間,沒有next的執行,就不會執行下一個動做。
clearInterval(timer);
}
}, 30);
}).animate({left: 200}, 2000);
F-------------------- delay(2000) 延遲2秒鐘
$('#test').click(function () {
$(this).animate({width: 400}, 2000).delay(2000).animate({left: 200}, 2000);
});
G--------------------- promise 全部運動執行完成之後,執行 promise 掛載的函數。
$('#test').click(function () {
$(this).animate({width: 400}, 2000).delay(2000).animate({left: 200}, 2000);
$(this).promise().done(function () {
alert('done');
});
});
});
源碼:
jQuery.extend({
queue: function( elem, type, data ) {
var queue;
// 當元素存在的時候
if ( elem ) {
// 能夠直接寫一個type類型,不寫默認就是fx
type = ( type || "fx" ) + "queue";
queue = data_priv.get( elem, type ); // 如何往隊列中存儲,獲得數組
// Speed up dequeue by getting out quickly if this is just a lookup
// 若是存在第三個參數,就是傳入的執行函數。
if ( data ) {
// 判斷 queue 是否存在,若是不存在,就執行,建立一個。
// 或者存入的 data 是數組,就重寫,並覆蓋之前的全部方法。搞一個新的 隊列 queue 。
if ( !queue || jQuery.isArray( data ) ) {
// 設定數據。
queue = data_priv.access( elem, type, jQuery.makeArray(data) );
}
// 存在,就壓入。
else {
queue.push( data );
}
}
// 沒有酒返回空數組,寫2個參數,就返回集合。
return queue || [];
}
},
// 出隊
dequeue: function( elem, type ) {
// 不寫就默認fx
type = type || "fx";
// 先去獲得 queue 的隊列。
var queue = jQuery.queue( elem, type ), // queue 初始化。
startLength = queue.length, // 獲取數組長度。
// 返回第一項。
fn = queue.shift(),
hooks = jQuery._queueHooks( elem, type ),
// 出隊的操做 next(), 跟 dequeue 一回事。
next = function() {
jQuery.dequeue( elem, type );
};
// If the fx queue is dequeued, always remove the progress sentinel
// 當定時器結束的時候, 進行出隊。
if ( fn === "inprogress" ) {
fn = queue.shift();
startLength--; // 長度 - 1
}
// 是不是函數。
if ( fn ) {
// Add a progress sentinel to prevent the fx queue from being
// automatically dequeued
// 是默認狀況下,就填入。
if ( type === "fx" ) {
// inprogress 針對fx。添加 inprogress
// 只有三處用了 inprogress。
// inprogress 的做用就是讓隊列,能夠自動的進行出隊的操做。
queue.unshift( "inprogress" ); // 只有第一次,添加
}
// clear up the last queue stop function
delete hooks.stop;
// fn 是隊列 剛退出來的函數, 傳入參數, 進行call執行。
fn.call( elem, next, hooks );
}
if ( !startLength && hooks ) {
hooks.empty.fire();
}
},
// not intended for public consumption - generates a queueHooks object, or returns the current one
// 私有的函數,清理一下緩存。
// _queueHooks 的目的就是,將fx(默認),或者用戶傳入的的隊列名,---->> 這些都是緩存到data中了,
// 當所有結束的時候,將那些 fixqueue, 等,對咧名稱,所有幹掉。
_queueHooks: function( elem, type ) {
var key = type + "queueHooks";
// data_priv.get( elem, key ) 取緩存,沒有酒添加一個。
//
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 ] );
})
});
}
});
實例的源碼
jQuery.fn.extend({
queue: function( type, data ) {
var setter = 2;
判斷是不是字符串。若是不是字符串,那麼可能傳入的是函數,或者數組。
if ( typeof type !== "string" ) {
data = type;
type = "fx";
setter--;
}
// 查看的狀態
// 傳入的參數小於2.
if ( arguments.length < setter ) {
return jQuery.queue( this[0], type ); // 返回一組元素的第一項。
}
// 若果是空的話,就返回this對象,若是不是空,就要遍歷了。
return data === undefined ?
this :
this.each(function() {
var queue = jQuery.queue( this, type, data );
// ensure a hooks for this queue
//這裏:_queueHooks了之後,看這個是否是空的,若是不是,就填入一個數據。
jQuery._queueHooks( this, type );
// 隊列第0項,不是 inprogress 就出隊,只是針對第一次出隊操做,後續就不會了。 // 針對animate運動的。$(document).queue('p1', aaa).$(document).queue('p1', bbb); // 若是連續多個操做,第一個就直接執行了,而後第二個進入隊列。
// inprogress乾的就是這個。保證執行第一個,後面的進行入隊操做,等待前面的結束,激活後面的。 // 這裏,$(document).queue('p1', aaa) 執行完,就要出隊,而後再執行後面的動做。 // 這是一個入隊方法,可是爲何調用出隊呢? // 針對的就是這個 $(document).queue('p1', aaa) 第一個要直接運動起來。後面的壓入隊列,等待第一個執行結束,在進行後面的. // 邏輯比較簡單
if ( type === "fx" && queue[0] !== "inprogress" ) {
// 出隊
jQuery.dequeue( this, type ); //遞歸了。又從新調用。
}
});
},
dequeue: function( type ) {
return this.each(function() {
jQuery.dequeue( this, type );
});
},
// Based off of the plugin by Clint Helfers, with permission.
//
// 延遲時間的。time == 600
delay: function( time, type ) {
time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
type = type || "fx";
return this.queue( type, function( next, hooks ) {
// 這裏搞了一個定時器,讓你 time 時間之後,再進行出隊操做。
var timeout = setTimeout( next, time );
hooks.stop = function() {
clearTimeout( timeout );
};
});
},
// 清空
clearQueue: function( type ) {
return this.queue( type || "fx", [] );
},
// 這裏和 Deferred 和 callbacks 裏面的東西差很少。 // 就是等到運動結束了,執行個函數什麼的, 讓promise去執行就行了。
// Get a promise resolved when queues of a certain type
// are emptied (fx is the type by default)
promise: function( type, obj ) {
var tmp,
// 計數
count = 1,
// Deferred 的對象
defer = jQuery.Deferred(),
elements = this,
i = this.length,
// 累加多少,就減多少。
resolve = function() {
// 直到 count == 0 的時候,纔會執行這個 resolveWith--》》就是完成了---》》而後就是done。 // 這裏就不存在fail了。
if ( !( --count ) ) {
defer.resolveWith( elements, [ elements ] );
}
};
if ( typeof type !== "string" ) {
obj = type;
type = undefined;
}
type = type || "fx";
while( i-- ) {
tmp = data_priv.get( elements[ i ], type + "queueHooks" );
if ( tmp && tmp.empty ) { //這個隊列存在的時候,就進行累加。
count++;
tmp.empty.add( resolve ); // 添加事件
}
}
resolve(); // 內部函數調用,
return defer.promise( obj );
}
});