摘要:作為此時不存在,直接從數(shù)據(jù)緩存中獲取并返回。作用是觸發(fā)中的回調(diào)函數(shù),的表示只讓觸發(fā)一次后,就需要清理,表示是將清空成空數(shù)組還是空字符。
前言:
queue()方法和dequeue()方法是為 jQuery 的動畫服務(wù)的,目的是為了允許一系列動畫函數(shù)被異步調(diào)用,但不會阻塞程序。
所以這篇是為jQuery的動畫解析做準(zhǔn)備的。
一、$.queue()、$.dequeue() 和 $().queue()、$().dequeue() 的區(qū)別
(1)$().queue()和$().dequeue()
這倆是jQuery.fn.extend()中的方法,也就是供開發(fā)者使用的方法,其內(nèi)部會分別調(diào)用 $.queue()和$.dequeue()方法。
//源碼4686行 jQuery.fn.extend( { queue: function( type, data ) { xxx return jQuery.queue( this[ 0 ], type ) }, dequeue: function( type, data ) { return jQuery.dequeue( this, type ) }, })
(2)$.queue()和$.dequeue()
這倆是jQuery.extend()中的方法,也就是 jQuery 內(nèi)部使用的方法。
//源碼4594行 jQuery.extend( { queue: function( elem, type, data ) {}, dequeue: function( elem, type ) {}, })
二、$().queue()
作用1:
作為setter,將function(){}存進(jìn)特定隊列中。
這是A
作用2:
作為getter,取出特定隊列中function(){}的數(shù)組。
/*getter*/ $("#A").queue("type") //[a,b]
源碼:
jQuery.fn.extend( { //入隊 //源碼4663行 //"type", function(){xxx} queue: function( type, data ) { var setter = 2; if ( typeof type !== "string" ) { data = type; type = "fx"; setter--; } //如果參數(shù)小于setter,就執(zhí)行jQuery.queue()方法 /*這邊就是getter*/ if ( arguments.length < setter ) { //this[0] 目標(biāo)DOM元素 //type "type" //返回[function a(){xxx},function b(){xxx}] return jQuery.queue( this[ 0 ], type ); } //如果data是undefined就返回jQuery對象 return data === undefined ? this : this.each( function() { /*這邊是setter*/ var queue = jQuery.queue( this, type, data ); // Ensure a hooks for this queue //確保該隊列有一個hooks //返回{empty:{ // 里面是jQuery.Callbacks方法 // 其中add方法被改寫 // }} jQuery._queueHooks( this, type ); /*專門為fx動畫做處理*/ if ( type === "fx" && queue[ 0 ] !== "inprogress" ) { jQuery.dequeue( this, type ); } } ); }, })
解析:
不涉及 fx 動畫的話,本質(zhì)是調(diào)用的內(nèi)部的jQuery.queue()方法
(1)如果不足兩個參數(shù)的話,就調(diào)用jQuery. queue()來get獲取數(shù)據(jù)。
(2)如果大于等于兩個參數(shù)的話,就調(diào)用jQuery. queue()來set存數(shù)據(jù),并且調(diào)用jQuery._queueHooks(),用來生成一個queueHooks對象或者返回當(dāng)前值。
(3)如果是 fx 動畫,并且隊頭沒有inprogress鎖的話,就執(zhí)行jQuery.dequeue()方法。
三、jQuery._queueHooks()
作用:
如果目標(biāo)元素的數(shù)據(jù)緩存(dataPriv)已存在名稱type+queueHooks的Hooks話,則直接返回該Hooks,
否則返回有empty屬性的jQuery.Callback()方法生成的對象:
其中的fire()方法用來清除隊列。
源碼:
// Not public - generate a queueHooks object, or return the current one //jQuery內(nèi)部方法,生成一個queueHooks對象或者返回當(dāng)前值 //目標(biāo)元素,"type" //源碼4676行 _queueHooks: function( elem, type ) { //typequeueHooks var key = type + "queueHooks"; //如果dataPriv已存在名稱typequeueHooks的Hooks話,則直接返回該Hooks //否則返回有empty屬性的jQuery.Callback()方法生成的對象 return dataPriv.get( elem, key ) || dataPriv.access( elem, key, { empty: jQuery.Callbacks( "once memory" ).add( function() { dataPriv.remove( elem, [ type + "queue", key ] ); } ) } ); }
解析:
jQuery.Callbacks()方法會放到$.dequeue后講解
四、jQuery.queue()
作用:
把callback依次存入目標(biāo)元素的queue中,或者取出queue。
源碼:
jQuery.extend( { //作用:目標(biāo)元素可執(zhí)行的任務(wù)隊列 //源碼4596行 //elem 目標(biāo)元素 //$("#A"),"type",function(){xxx} queue: function( elem, type, data ) { var queue; if ( elem ) { //typequeue type = ( type || "fx" ) + "queue"; //從數(shù)據(jù)緩存中獲取typequeue隊列,如果沒有則為undefined queue = dataPriv.get( elem, type ); // Speed up dequeue by getting out quickly if this is just a lookup if ( data ) { //如果queue不存在,或者data是Array的話 //就創(chuàng)建queue,queue=[data1,data2,...] if ( !queue || Array.isArray( data ) ) { queue = dataPriv.access( elem, type, jQuery.makeArray( data ) ); } //queue存在的話,就把data push進(jìn)去 else { queue.push( data ); } } //queue=[a,b] return queue || []; } }, })
解析:
(1)作為setter
function a() { console.log("a","a34") } $("#A").queue("type", a)
此時data存在,并且是第一次創(chuàng)建type="type"的queue,所以使用dataPriv.access( elem, type, jQuery.makeArray( data ) )來創(chuàng)建queue,并把function a push 進(jìn)queue中。
(2)作為getter
$("#A").queue("type") //[a,b]
此時data不存在,直接從數(shù)據(jù)緩存中獲取queue并返回。
注意:
jQuery.queue()始終返回queue數(shù)組,而$().queue()會返回 jQuery 對象或者是queue數(shù)組。
五、$().dequeue()
作用:
移出隊頭的函數(shù)并執(zhí)行該callback。
源碼:
jQuery.fn.extend( { //出隊 //移出隊頭的函數(shù)并執(zhí)行它 //源碼4717行 dequeue: function( type ) { return this.each( function() { jQuery.dequeue( this, type ); } ); }, })
解析:
其實就是執(zhí)行$.dequeue()函數(shù)。
六、jQuery.dequeue()
作用:
同五。
源碼:
jQuery.extend( { //源碼4624行 //目標(biāo)元素,"type" dequeue: function( elem, type ) { //"type" type = type || "fx"; //get,獲取目標(biāo)元素的隊列 var queue = jQuery.queue( elem, type ), //長度 startLength = queue.length, //去除對首元素,并返回該元素 fn = queue.shift(), //確保該隊列有一個hooks hooks = jQuery._queueHooks( elem, type ), //next相當(dāng)于dequeue的觸發(fā)器 next = function() { jQuery.dequeue( elem, type ); }; // If the fx queue is dequeued, always remove the progress sentinel //如果fn="inprogress",說明是fx動畫隊列正在出隊,就移除inprogress if ( fn === "inprogress" ) { fn = queue.shift(); startLength--; } if ( fn ) { // Add a progress sentinel to prevent the fx queue from being // automatically dequeued //如果是fx動畫隊列的話,就添加inprogress標(biāo)志,來防止自動出隊執(zhí)行 //意思應(yīng)該是等上一個動畫執(zhí)行完畢后,再執(zhí)行下一個動畫 if ( type === "fx" ) { queue.unshift( "inprogress" ); } // Clear up the last queue stop function //刪除hooks的stop屬性方法 delete hooks.stop; //遞歸dequeue方法 fn.call( elem, next, hooks ); } console.log(startLength,"startLength4669") //如果隊列是一個空數(shù)組,并且hooks存在的話,清除該隊列 if ( !startLength && hooks ) { console.log("aaaa","bbbb4671") //進(jìn)行隊列清理 hooks.empty.fire(); } }, })
解析:
(1)inprogress應(yīng)該是一個鎖,當(dāng) fx 動畫執(zhí)行動畫 A 的時候,就加鎖,當(dāng)動畫 A 執(zhí)行完畢后,就解鎖,再去運行下一個動畫。
(2)注意下fn.call( elem, next, hooks ),保持fn的this是element的同時,給fn傳的兩個參數(shù),分別為next和hooks,方便操作。
(3)當(dāng)queue是空數(shù)組的時候,就觸發(fā)hooks.empty的fire()方法,將queue清除。
七、jQuery.Callbacks()
作用:
jQuery的callbacks回調(diào)方法,返回一個object,里面包含 a、b、c 方法,在執(zhí)行任意一個方法后,這個方法依舊返回 a、b、c 方法,所以jQuery.Callbacks()是鏈?zhǔn)秸{(diào)用的關(guān)鍵函數(shù)。
在_queueHooks 中有用到該函數(shù):
dataPriv.access( elem, key, { empty: jQuery.Callbacks( "once memory" ).add( function() { dataPriv.remove( elem, [ type + "queue", key ] ); } ) } );
源碼:
/*創(chuàng)建一個使用以下參數(shù)的callback列表 * Create a callback list using the following parameters: * options:是一個可選的空格分開的參數(shù),它可以改變callback列表的行為或形成新的option對象 * options: an optional list of space-separated options that will change how * the callback list behaves or a more traditional option object * 默認(rèn)情況下一個回調(diào)列表會表現(xiàn)成一個event callback列表并且會觸發(fā)多次 * By default a callback list will act like an event callback list and can be * "fired" multiple times. * option可選值: * Possible options: * 確保callback列表只會被觸發(fā)一次,比如Deferred對象 * once: will ensure the callback list can only be fired once (like a Deferred) * 保持跟蹤之前的values,并且會在list用最新的values觸發(fā)后,調(diào)用該回調(diào)函數(shù) * memory: will keep track of previous values and will call any callback added * after the list has been fired right away with the latest "memorized" * values (like a Deferred) * //確保callback只會被添加一次 * unique: will ensure a callback can only be added once (no duplicate in the list) * //當(dāng)callbak返回false時打斷調(diào)用 * stopOnFalse: interrupt callings when a callback returns false * */ //源碼3407行 //callbacks回調(diào)對象,函數(shù)的統(tǒng)一管理 //once memory jQuery.Callbacks = function( options ) { // Convert options from String-formatted to Object-formatted if needed // (we check in cache first) options = typeof options === "string" ? //options: {once:true,memory:true} createOptions( options ) : jQuery.extend( {}, options ); //用來知道list是否正被調(diào)用 var // Flag to know if list is currently firing firing, // Last fire value for non-forgettable lists memory, // Flag to know if list was already fired fired, // Flag to prevent firing locked, // Actual callback list list = [], // Queue of execution data for repeatable lists queue = [], // Index of currently firing callback (modified by add/remove as needed) firingIndex = -1, //觸發(fā)list中的回調(diào)函數(shù) // Fire callbacks fire = function() { //true // Enforce single-firing //"once memory"中的"once"只允許觸發(fā)一次 locked = locked || options.once; // Execute callbacks for all pending executions, // respecting firingIndex overrides and runtime changes fired = firing = true; for ( ; queue.length; firingIndex = -1 ) { //從queue移除第一個元素,并返回該元素 memory = queue.shift(); while ( ++firingIndex < list.length ) { // Run callback and check for early termination //memory=[document, Array(1)] //memory[0]是document //意思就是讓document去執(zhí)行add()方法中添加的callback函數(shù) if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false && options.stopOnFalse ) { // Jump to end and forget the data so .add doesn"t re-fire firingIndex = list.length; memory = false; } } } // Forget the data if we"re done with it if ( !options.memory ) { memory = false; } firing = false; // Clean up if we"re done firing for good //如果once:true,清空list數(shù)組 if ( locked ) { // Keep an empty list if we have data for future add calls if ( memory ) { list = []; // Otherwise, this object is spent } else { list = ""; } } }, // Actual Callbacks object self = { //添加一個回調(diào)函數(shù)或者是一個回調(diào)函數(shù)的集合 // Add a callback or a collection of callbacks to the list add: function() { if ( list ) { // If we have memory from a past run, we should fire after adding if ( memory && !firing ) { firingIndex = list.length - 1; queue.push( memory ); } //閉包 //將arguments作為參數(shù)即args傳入閉包的add方法中 ( function add( args ) { //args[0]即function(){dataPriv.remove( elem, [ type + "queue", key ] ) } jQuery.each( args, function( _, arg ) { if ( isFunction( arg ) ) { //如果self對象沒有該方法,將其push進(jìn)list中 if ( !options.unique || !self.has( arg ) ) { list.push( arg ); } } else if ( arg && arg.length && toType( arg ) !== "string" ) { // Inspect recursively add( arg ); } } ); } )( arguments ); //undefined undefined if ( memory && !firing ) { fire(); } } //this即self對象 //也就說在調(diào)用self對象內(nèi)的方法后會返回self對象本身 return this; }, // Remove a callback from the list remove: function() { jQuery.each( arguments, function( _, arg ) { var index; while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { list.splice( index, 1 ); // Handle firing indexes if ( index <= firingIndex ) { firingIndex--; } } } ); return this; }, // Check if a given callback is in the list. // If no argument is given, return whether or not list has callbacks attached. has: function( fn ) { return fn ? jQuery.inArray( fn, list ) > -1 : list.length > 0; }, // Remove all callbacks from the list empty: function() { if ( list ) { list = []; } return this; }, // Disable .fire and .add // Abort any current/pending executions // Clear all callbacks and values disable: function() { locked = queue = []; list = memory = ""; return this; }, disabled: function() { return !list; }, // Disable .fire // Also disable .add unless we have memory (since it would have no effect) // Abort any pending executions lock: function() { locked = queue = []; if ( !memory && !firing ) { list = memory = ""; } return this; }, locked: function() { return !!locked; }, // Call all callbacks with the given context and arguments fireWith: function( context, args ) { if ( !locked ) { args = args || []; args = [ context, args.slice ? args.slice() : args ]; queue.push( args ); if ( !firing ) { fire(); } } return this; }, // Call all the callbacks with the given arguments fire: function() { self.fireWith( this, arguments ); return this; }, // To know if the callbacks have already been called at least once fired: function() { return !!fired; } }; console.log(queue,"queue3614") return self; };
解析:
主要看add()和fire()方法
(1)self.add()
注意里面的閉包函數(shù),使用閉包的目的是凍結(jié)args的值,這樣可以避免異步調(diào)用造成的值得改變。
add()方法就是將function() {dataPriv.remove( elem, [ type + "queue", key ] );}push 進(jìn) list 數(shù)組中,以供fire()來調(diào)用 list 中的callback。
注意最后返回的是this,即self對象,也就說在調(diào)用self對象內(nèi)的方法后會返回self對象本身,而self內(nèi)部又含有add()、fire()等方法,通過jQuery.Callbacks傳入的參數(shù)options來控制能否調(diào)用,及調(diào)用的次數(shù)。
(2)self.fire()
作用是觸發(fā) list 中的回調(diào)函數(shù),onece memory的once表示只讓fire()觸發(fā)一次后,就需要清理 list,memory表示是將 list 清空成空數(shù)組還是空字符。
八、createOptions()
作用:
將特定格式的string(空格分開),轉(zhuǎn)化為特定格式的object({xxx:true,xxx:true,...} .
源碼:
//將特定格式的string(空格分開),轉(zhuǎn)化為特定格式的object({xxx:true,xxx:true,...}) // Convert String-formatted options into Object-formatted ones //源碼3377行 //"once memory" —> {once:true,memory:true} function createOptions( options ) { var object = {}; jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) { object[ flag ] = true; } ); return object; }
解析:
將以空格連接的字符串,以空格拆開,并作為 object 的key,其 value 為 true
比如:
"once memory" => {once:true,memory:true,}
(完)
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/104920.html
摘要:前言需要先看源碼解析之和一舉例的寬度先變成,再變成,最后變成這是在異步調(diào)用中,進(jìn)行同步調(diào)用動畫是異步的就是連續(xù)調(diào)用二作用通過樣式將元素從一個狀態(tài)改變?yōu)榱硪粋€狀態(tài)源碼之前有說過是的方法源碼行是否是空對象,方法執(zhí)行單個動畫的封裝的本質(zhì)是執(zhí)行 showImg(https://segmentfault.com/img/remote/1460000019594521); 前言:需要先看 jQue...
摘要:根據(jù)項目選型決定是否開啟。為了壓縮,可維護(hù)為了支持從而使用代替變量存儲防沖突會用到,形如版本號聲明最終調(diào)用的是這個原型實際上。功能檢測統(tǒng)一兼容性問題。 概覽 (function (){ (21 , 94) 定義了一些變量和函數(shù) jQuery=function(); (96 , 293) 給jQuery對象添加一些方法和屬性; (285 , 347) ...
摘要:根據(jù)項目選型決定是否開啟。為了壓縮,可維護(hù)為了支持從而使用代替變量存儲防沖突會用到,形如版本號聲明最終調(diào)用的是這個原型實際上。功能檢測統(tǒng)一兼容性問題。 概覽 (function (){ (21 , 94) 定義了一些變量和函數(shù) jQuery=function(); (96 , 293) 給jQuery對象添加一些方法和屬性; (285 , 347) ...
閱讀 980·2021-11-17 09:33
閱讀 435·2019-08-30 11:16
閱讀 2498·2019-08-29 16:05
閱讀 3374·2019-08-29 15:28
閱讀 1422·2019-08-29 11:29
閱讀 1975·2019-08-26 13:51
閱讀 3415·2019-08-26 11:55
閱讀 1239·2019-08-26 11:31