jQuery 源碼 : queue 主要針對animate這個操做

 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 ); } });
相關文章
相關標籤/搜索