>

jquery1.83 从前全体与异步列队相关的模块详细介绍

- 编辑:乐百家599手机首页 -

jquery1.83 从前全体与异步列队相关的模块详细介绍

Deferred在1.5是两个_Deferred的合体,但1 1不对等2,它照旧做了抓牢。偷偷揭发,Deferred本来是python世界知名的Twisted框架的事物,由最先七大JS类库中的MochiKit取经回来,最终被dojo承继衣钵。jQuery之所以那样构造Deferred,鲜明不愿背抄袭的骂名,于是方法改得一无可取,是jQuery命名最差的API,完全不知所云。它还参预当时正在火热批评的promise机制。下面是二个相比列表:

           }

            if ( data === undefined && this.length )
                data = jQuery.data( this[0], key ); 

1.6添加了_mark,_unmark,promise。queue是让函数同属多少个队伍容貌中间,指标是让动画片八个接三个实行。_mark则是让它们各自全体阵容,并列施行(尽管它们只记录异步列队中已被施行的函数个数)。promise则在这几个出现施行的动画片试行后才实施另些一些回调(或动画)。

                  // 这里并从未看清data的档期的顺序,不管data是还是不是函数

    removeData: function( key ){
        return this.each(function(){
            jQuery.removeData( this, key );
        });
    }
});

(function( jQuery ) {
function handleQueueMarkDefer( elem, type, src ) {
var deferDataKey = type "defer",
queueDataKey = type "queue",
markDataKey = type "mark",
defer = jQuery._data( elem, deferDataKey );
if ( defer &&
( src === "queue" || !jQuery._data(elem, queueDataKey) ) &&
( src === "mark" || !jQuery._data(elem, markDataKey) ) ) {
// Give room for hard-coded callbacks to fire first
// and eventually mark/queue something else on the element
setTimeout( function() {
if ( !jQuery._data( elem, queueDataKey ) &&
!jQuery._data( elem, markDataKey ) ) {
jQuery.removeData( elem, deferDataKey, true );
defer.fire();
}
}, 0 );
}
}
jQuery.extend({
_mark: function( elem, type ) {
if ( elem ) {
type = ( type || "fx" ) "mark";
jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) 1 );
}
},
_unmark: function( force, elem, type ) {
if ( force !== true ) {
type = elem;
elem = force;
force = false;
}
if ( elem ) {
type = type || "fx";
var key = type "mark",
count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );
if ( count ) {
jQuery._data( elem, key, count );
} else {
jQuery.removeData( elem, key, true );
handleQueueMarkDefer( elem, type, "mark" );
}
}
},
queue: function( elem, type, data ) {
var q;
if ( elem ) {
type = ( type || "fx" ) "queue";
q = jQuery._data( elem, type );
// Speed up dequeue by getting out quickly if this is just a lookup
if ( data ) {
if ( !q || jQuery.isArray(data) ) {
q = jQuery._data( elem, type, jQuery.makeArray(data) );
} else {
q.push( data );
}
}
return q || [];
}
},
dequeue: function( elem, type ) {
type = type || "fx";
var queue = jQuery.queue( elem, type ),
fn = queue.shift(),
hooks = {};
// If the fx queue is dequeued, always remove the progress sentinel
if ( fn === "inprogress" ) {
fn = queue.shift();
}
if ( fn ) {
// Add a progress sentinel to prevent the fx queue from being
// automatically dequeued
if ( type === "fx" ) {
queue.unshift( "inprogress" );
}
jQuery._data( elem, type ".run", hooks );
fn.call( elem, function() {
jQuery.dequeue( elem, type );
}, hooks );
}
if ( !queue.length ) {
jQuery.removeData( elem, type "queue " type ".run", true );
handleQueueMarkDefer( elem, type, "queue" );
}
}
});
jQuery.fn.extend({
queue: function( type, data ) {
var setter = 2;
if ( typeof type !== "string" ) {
data = type;
type = "fx";
setter--;
}
if ( arguments.length < setter ) {
return jQuery.queue( this[0], type );
}
return data === undefined ?
this :
this.each(function() {
var queue = jQuery.queue( this, type, data );
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.
//
delay: function( time, type ) {
time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
type = type || "fx";
return this.queue( type, function( next, hooks ) {
var timeout = setTimeout( next, time );
hooks.stop = function() {
clearTimeout( timeout );
};
});
},
clearQueue: function( type ) {
return this.queue( type || "fx", [] );
},
// Get a promise resolved when queues of a certain type
// are emptied (fx is the type by default)
promise: function( type, object ) {
if ( typeof type !== "string" ) {
object = type;
type = undefined;
}
type = type || "fx";
var defer = jQuery.Deferred(),
elements = this,
i = elements.length,
count = 1,
deferDataKey = type "defer",
queueDataKey = type "queue",
markDataKey = type "mark",
tmp;
function resolve() {
if ( !( --count ) ) {
defer.resolveWith( elements, [ elements ] );
}
}
while( i-- ) {
if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||
( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||
jQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&
jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) {
count ;
tmp.add( resolve );
}
}
resolve();
return defer.promise( object );
}
});
})( jQuery );

 

3. 【queue([name])】,【queue([name],callback)】和【queue([name],queue】

复制代码 代码如下:

                     if ( display === "inline" ) {

            if ( !name )
                jQuery.removeData( elem );
        } 

(function( jQuery ) {
var topics = {},
sliceTopic = [].slice;
jQuery.Topic = function( id ) {
var callbacks,
method,
topic = id && topics[ id ];
if ( !topic ) {
callbacks = jQuery.Callbacks();
topic = {
publish: callbacks.fire,
subscribe: callbacks.add,
unsubscribe: callbacks.remove
};
if ( id ) {
topics[ id ] = topic;
}
}
return topic;
};
jQuery.extend({
subscribe: function( id ) {
var topic = jQuery.Topic( id ),
args = sliceTopic.call( arguments, 1 );
topic.subscribe.apply( topic, args );
return {
topic: topic,
args: args
};
},
unsubscribe: function( id ) {
var topic = id && id.topic || jQuery.Topic( id );
topic.unsubscribe.apply( topic, id && id.args ||
sliceTopic.call( arguments, 1 ) );
},
publish: function( id ) {
var topic = jQuery.Topic( id );
topic.publish.apply( topic, sliceTopic.call( arguments, 1 ) );
}
});
})( jQuery );

       if ( !queue.length ) {

吃透,重临elem的索引值。

queue那边也没变多少。

           if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||

        var q = jQuery.data( elem, type ); 

复制代码 代码如下:

    _mark: function( elem, type ) {

例子

var log = function(msg){
window.console && console.log(msg)
}
function asyncThing1(){
var dfd = $.Deferred();
setTimeout(function(){
log('asyncThing1 seems to be done...');
dfd.resolve('1111');
},1000);
return dfd.promise();
}
function asyncThing2(){
var dfd = $.Deferred();
setTimeout(function(){
log('asyncThing2 seems to be done...');
dfd.resolve('222');
},1500);
return dfd.promise();
}
function asyncThing3(){
var dfd = $.Deferred();
setTimeout(function(){
log('asyncThing3 seems to be done...');
dfd.resolve('333');
},2000);
return dfd.promise();
}
/* do it */
$.when( asyncThing1(), asyncThing2(), asyncThing3() ).done(function(res1, res2, res3){
log('all done!');
log(res1 ', ' res2 ', ' res3);
})

       var queue = jQuery.queue( elem, type ), // 收取队列,调用queue时type产生了type quque

在要素上移除存放的多少。具体达成如下:

复制代码 代码如下:

       // 借使施行完成,则调用jQuery.removeData移除type钦赐的系列

再看第三行的事例,queue的第1个参数为二个数组,实际上它能够是三个新队列只怕现存队列去替代当前队列,个中新队列可能现成队列的值和queue(callback)同样。

并且,动画模块迎来了它首回大重构,它也可以有三个钩子Tween.propHooks。它多出多少个对象,当中Animation再次来到二个异步列队,Tween 是用来拍卖单个样式或质量的扭转,也正是从前Fx对象。animate被抽空了,它在1.柒十二只是近百行的框框。jQuery通过钩子机制与差异出一部分新的目的,将一部分重型方法重构掉。以后可怜长的措施只龟缩在节点模块,回调模块。

"jQuery161017518149125935123"

二、数据缓存

复制代码 代码如下:

           type = (type || "fx") "queue"; // 改名,每一种都要增长queue

dequeue: function(type){
    return this.each(function(){
        jQuery.dequeue( this, type );
    });
}

一旦大家想赢得各类异步的结果,我们须求用resolve, resolveWith, reject, rejectWith进行传递它们。

    // queue为false,动画马上起头,不可是放入动画队列

当不富含num时,调用jQuery.makeArray方法,具体贯彻如下:

jQuery1.7,从deferred模块中不同出callback模块,其实正是事先的_Deferred的加强版,增多去重,锁定,return false时中断试行下三个回调,清空等功能。

       }

$(this).get(0)与$(this)[0]等价。

复制代码 代码如下:

           }

jQuery.fn.extend({
    data: function( key, value ){
        var parts = key.split(".");
        parts[1] = parts[1] ? "."   parts[1] : ""; 

function fn(){
return 4;
}
function log(s){
window.console && console.log(s)
}
$.when( { num:1 }, 2, '3', fn() ).done(function(o1, o2, o3, o4){
log(o1.num);
log(o2);
log(o3);
log(o4);
});

           type = "fx";

HTML代码 jQuery代码
<div id="foobar"><div></div><div id="foo"></div></div>

$("div").index($('#foobar')[0]) // 0
$("div").index($('#foo')[0]) // 2
$("div").index($('#foo')) // -1

异步列队一发端没什么人用(未来也未有怎么人用,概念太肤浅了,方法名起得太烂了),于是它不得不在里头自产自销。首先被染指的是queue。queue模块是1.4为诱惑社区的delay插件,特地从data模块中不同的产物,而data则是从event模块化分出来的。jQuery新模块的出世总是因为客商对已有API的受制制不满而致。最先的queue模块的源码:

                  }

size: function() {
    return this.length;
}

复制代码 代码如下:

    // 用在动画animate中

        // 当我们试着访谈叁个键是否含有值的时候,要是不设有jQuery.cache[id]值, 初始化jQuery.cache[id]值
        if ( name && !jQuery.cache[ id ] )
            jQuery.cache[ id ] = {}; 

那儿,钩子机制其实早已在jQuery内部蔓延起来,1.5是css模块的cssHooks,1.6是性质模块的attrHooks, propHooks, boolHooks, nodeHooks,1.7是事件模块的fixHooks, keyHooks, mouseHooks,1.8是queue模块的_queueHooks,由于_queueHooks,queue终于塑身了。

白日干活,不管忙不忙,jQuery源码解析种类只可以放在早晨写,常常看的对象大概也留神到创新时间一般是黎明(英文名:lí míng),平常觉的挺累的,想前天算了吧上床睡前天再说啊,但要么坚贞不屈下去了,笔者会尽量要求本身1-2天发表一篇。刚最初写的时候,有个别顾虑写出来的东西会幼稚肤浅或讲不领会,有个别地点也确确实实是那般,那一个假日让自身想领悟了广大事,现在的稿子接待各位道友拍各样砖和石块,用力点,不要停。

 

到目前截至,全部异步的东西都被jQuery改产生异步列队的“子类”或叫“变种”更合适些。如domReady, 动画,AJAX,与实践了promise或delay或各个特效方法之后的jQuery对象。于是全部异步的东西在promise的加强护理下,像一只那样编写异步程序。

           var queue = jQuery.queue( this, type, data );

接下来查看jQuery.dequeue方法的有血有肉落实如下:

就算把大气代码移动callbacks,但1.7的Deferred却一点未曾没变小,它变得越来越大型,它由多少个函数列队组成了。何况重回的是Promise对象,比原本多出了pipe, state, progress, always方法。ajax这边就改为那样:

           name = jQuery.camelCase( p );

    }
    return q;
}

View Code?//1.8
jQuery.extend({
queue: function( elem, type, data ) {
var queue;
if ( elem ) {
type = ( type || "fx" ) "queue";
queue = jQuery._data( elem, type );
// Speed up dequeue by getting out quickly if this is just a lookup
if ( data ) {
if ( !queue || jQuery.isArray(data) ) {
queue = jQuery._data( elem, type, jQuery.makeArray(data) );
} else {
queue.push( data );
}
}
return queue || [];
}
},
dequeue: function( elem, type ) {
type = type || "fx";
var queue = jQuery.queue( elem, type ),
fn = queue.shift(),
hooks = jQuery._queueHooks( elem, type ),
next = function() {
jQuery.dequeue( elem, type );
};
// If the fx queue is dequeued, always remove the progress sentinel
if ( fn === "inprogress" ) {
fn = queue.shift();
}
if ( fn ) {
// Add a progress sentinel to prevent the fx queue from being
// automatically dequeued
if ( type === "fx" ) {
queue.unshift( "inprogress" );
}
// clear up the last queue stop function
delete hooks.stop;
fn.call( elem, next, hooks );
}
if ( !queue.length && hooks ) {
hooks.empty.fire();
}
},
// not intended for public consumption - generates a queueHooks object, or returns the current one
_queueHooks: function( elem, type ) {
var key = type "queueHooks";
return jQuery._data( elem, key ) || jQuery._data( elem, key, {
empty: jQuery.Callbacks("once memory").add(function() {
jQuery.removeData( elem, type "queue", true );
jQuery.removeData( elem, key, true );
})
});
}
});
jQuery.fn.extend({
queue: function( type, data ) {
var setter = 2;
if ( typeof type !== "string" ) {
data = type;
type = "fx";
setter--;
}
if ( arguments.length < setter ) {
return jQuery.queue( this[0], type );
}
return data === undefined ?
this :
this.each(function() {
var queue = jQuery.queue( this, type, data );
// ensure a hooks for this queue
jQuery._queueHooks( this, type );
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.
//
delay: function( time, type ) {
time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
type = type || "fx";
return this.queue( type, function( next, hooks ) {
var timeout = setTimeout( next, time );
hooks.stop = function() {
clearTimeout( timeout );
};
});
},
clearQueue: function( type ) {
return this.queue( type || "fx", [] );
},
// 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,
defer = jQuery.Deferred(),
elements = this,
i = this.length,
resolve = function() {
if ( !( --count ) ) {
defer.resolveWith( elements, [ elements ] );
}
};
if ( typeof type !== "string" ) {
obj = type;
type = undefined;
}
type = type || "fx";
while( i-- ) {
if ( (tmp = jQuery._data( elements[ i ], type "queueHooks" )) && tmp.empty ) {
count ;
tmp.empty.add( resolve );
}
}
resolve();
return defer.promise( obj );
}
});

 

例子

(function( jQuery ) {
function handleQueueMarkDefer( elem, type, src ) {
//清空记录deferred个数的字段,函数列队与异步列队
var deferDataKey = type "defer",
queueDataKey = type "queue",
markDataKey = type "mark",
defer = jQuery.data( elem, deferDataKey, undefined, true );
if ( defer &&
( src === "queue" || !jQuery.data( elem, queueDataKey, undefined, true ) ) &&
( src === "mark" || !jQuery.data( elem, markDataKey, undefined, true ) ) ) {
// Give room for hard-coded callbacks to fire first
// and eventually mark/queue something else on the element
setTimeout( function() {
if ( !jQuery.data( elem, queueDataKey, undefined, true ) &&
!jQuery.data( elem, markDataKey, undefined, true ) ) {
jQuery.removeData( elem, deferDataKey, true );
defer.resolve();
}
}, 0 );
}
}
jQuery.extend({
_mark: function( elem, type ) {
if ( elem ) {
type = (type || "fx") "mark";//创制三个以mark为后缀的字段,用于记录此列队中个数
jQuery.data( elem, type, (jQuery.data(elem,type,undefined,true) || 0) 1, true );
}
},
_unmark: function( force, elem, type ) {
if ( force !== true ) {
type = elem;
elem = force;
force = false;
}
if ( elem ) {
type = type || "fx";
var key = type "mark",
//让个数减1,借使第多少个参数为true,就强逼减至0
count = force ? 0 : ( (jQuery.data( elem, key, undefined, true) || 1 ) - 1 );
if ( count ) {
jQuery.data( elem, key, count, true );
} else {//如若为0,就移除它
jQuery.removeData( elem, key, true );
handleQueueMarkDefer( elem, type, "mark" );
}
}
},
queue: function( elem, type, data ) {
if ( elem ) {
type = (type || "fx") "queue";
var q = jQuery.data( elem, type, undefined, true );
// Speed up dequeue by getting out quickly if this is just a lookup
if ( data ) {
if ( !q || jQuery.isArray(data) ) {
q = jQuery.data( elem, type, jQuery.makeArray(data), true );
} else {
q.push( data );
}
}
return q || [];
}
},
dequeue: function( elem, type ) {
type = type || "fx";
var queue = jQuery.queue( elem, type ),
fn = queue.shift(),
defer;
// If the fx queue is dequeued, always remove the progress sentinel
if ( fn === "inprogress" ) {
fn = queue.shift();
}
if ( fn ) {
// Add a progress sentinel to prevent the fx queue from being
// automatically dequeued
if ( type === "fx" ) {
queue.unshift("inprogress");
}
fn.call(elem, function() {
jQuery.dequeue(elem, type);
});
}
if ( !queue.length ) {
jQuery.removeData( elem, type "queue", true );
handleQueueMarkDefer( elem, type, "queue" );
}
}
});
jQuery.fn.extend({
queue: function( type, data ) {
if ( typeof type !== "string" ) {
data = type;
type = "fx";
}
if ( data === undefined ) {
return jQuery.queue( this[0], type );
}
return this.each(function() {
var queue = jQuery.queue( this, type, data );
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.
//
delay: function( time, type ) {
time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;
type = type || "fx";
return this.queue( type, function() {
var elem = this;
setTimeout(function() {
jQuery.dequeue( elem, type );
}, time );
});
},
clearQueue: function( type ) {
return this.queue( type || "fx", [] );
},
//把jQuery对象装进两个异步列队,允许它在一多重动画中再实行之后绑定的回调
promise: function( type, object ) {
if ( typeof type !== "string" ) {
object = type;
type = undefined;
}
type = type || "fx";
var defer = jQuery.Deferred(),
elements = this,
i = elements.length,
count = 1,
deferDataKey = type "defer",
queueDataKey = type "queue",
markDataKey = type "mark";
function resolve() {
if ( !( --count ) ) {
defer.resolveWith( elements, [ elements ] );
}
}
while( i-- ) {
//假如它从前曾经使用过unmark, queue等办法,那么大家将生成三个新的Deferred放进缓存系统
if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||
( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||
jQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&
jQuery.data( elements[ i ], deferDataKey, jQuery._Deferred(), true ) )) {
count ;
tmp.done( resolve );
}
}
resolve();
return defer.promise();
}
});
})( jQuery );

           markDataKey = type "mark",

data(name,value)在要素上存放数据,同期也回到value。

$.when({aa:1}, {aa:2}).done(function(a,b){
console.log(a.aa)
console.log(b.aa)
});

                  } else {

上篇首要介绍JQuery的主导函数的法规机制,那篇将启幕介绍jQuery对象访谈和数量缓存原理,重要内容囊括:

那时期有还个小插曲,jQuery团队还想增添二个叫Topic的模块,内置公布者订阅者机制,但那封装太溥了,结果被否定。

              start = e.cur(); // 抽出当前值

queue: function( elem, type, data ) {
    if ( elem ){ 

jQuery.ajax模块也被染指,$.XH奥迪Q5对象,当作HTTPXMLRequest对象的仿造器是由三个Deferred对象与一个_Deferred的对象构成。

       }

inArray: function( elem, array ) {
    for ( var i = 0, length = array.length; i < length; i  )
    // Use === because on IE, window == document
        if ( array[ i ] === elem )
            return i; 

复制代码 代码如下:

>>> $.cache[5][$.expando]['testqueue']

// args 作为当中成员的调用来使用
each: function( object, callback, args ) {
    var name, i = 0, length = object.length;  // 当object为jQuery对象时,length非空

复制代码 代码如下:

 

removeData: function( elem, name ) {
    elem = elem == window ?
        windowData :
        elem; 

复制代码 代码如下:

       }

能够开采最终经过 fn=queue.shift();也许fn=queue[0]获得队列的首个成分,然后fn.call(elem);去试行它。

...

       function resolve() {

        type = (type || "fx")   "queue"; 

(function( jQuery ) {
// String to Object flags format cache
var flagsCache = {};
// Convert String-formatted flags into Object-formatted ones and store in cache
function createFlags( flags ) {
var object = flagsCache[ flags ] = {},
i, length;
flags = flags.split( /s / );
for ( i = 0, length = flags.length; i < length; i ) {
object[ flags[i] ] = true;
}
return object;
}
/*
* Create a callback list using the following parameters:
*
* flags: an optional list of space-separated flags that will change how
* the callback list behaves
*
* By default a callback list will act like an event callback list and can be
* "fired" multiple times.
*
* Possible flags:
*
* once: will ensure the callback list can only be fired once (like a Deferred)
*
* 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)
*
* unique: will ensure a callback can only be added once (no duplicate in the list)
*
* stopOnFalse: interrupt callings when a callback returns false
*
*/
jQuery.Callbacks = function( flags ) {
// Convert flags from String-formatted to Object-formatted
// (we check in cache first)
flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};
var // Actual callback list
list = [],
// Stack of fire calls for repeatable lists
stack = [],
// Last fire value (for non-forgettable lists)
memory,
// Flag to know if list is currently firing
firing,
// First callback to fire (used internally by add and fireWith)
firingStart,
// End of the loop when firing
firingLength,
// Index of currently firing callback (modified by remove if needed)
firingIndex,
// Add one or several callbacks to the list
add = function( args ) {
var i,
length,
elem,
type,
actual;
for ( i = 0, length = args.length; i < length; i ) {
elem = args[ i ];
type = jQuery.type( elem );
if ( type === "array" ) {
// Inspect recursively
add( elem );
} else if ( type === "function" ) {
// Add if not in unique mode and callback is not in
if ( !flags.unique || !self.has( elem ) ) {
list.push( elem );
}
}
}
},
// Fire callbacks
fire = function( context, args ) {
args = args || [];
memory = !flags.memory || [ context, args ];
firing = true;
firingIndex = firingStart || 0;
firingStart = 0;
firingLength = list.length;
for ( ; list && firingIndex < firingLength; firingIndex ) {
if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {
memory = true; // Mark as halted
break;
}
}
firing = false;
if ( list ) {
if ( !flags.once ) {
if ( stack && stack.length ) {
memory = stack.shift();
self.fireWith( memory[ 0 ], memory[ 1 ] );
}
} else if ( memory === true ) {
self.disable();
} else {
list = [];
}
}
},
// Actual Callbacks object
self = {
// Add a callback or a collection of callbacks to the list
add: function() {
if ( list ) {
var length = list.length;
add( arguments );
// Do we need to add the callbacks to the
// current firing batch?
if ( firing ) {
firingLength = list.length;
// With memory, if we're not firing then
// we should call right away, unless previous
// firing was halted (stopOnFalse)
} else if ( memory && memory !== true ) {
firingStart = length;
fire( memory[ 0 ], memory[ 1 ] );
}
}
return this;
},
// Remove a callback from the list
remove: function() {
if ( list ) {
var args = arguments,
argIndex = 0,
argLength = args.length;
for ( ; argIndex < argLength ; argIndex ) {
for ( var i = 0; i < list.length; i ) {
if ( args[ argIndex ] === list[ i ] ) {
// Handle firingIndex and firingLength
if ( firing ) {
if ( i <= firingLength ) {
firingLength--;
if ( i <= firingIndex ) {
firingIndex--;
}
}
}
// Remove the element
list.splice( i--, 1 );
// If we have some unicity property then
// we only need to do this once
if ( flags.unique ) {
break;
}
}
}
}
}
return this;
},
// Control if a given callback is in the list
has: function( fn ) {
if ( list ) {
var i = 0,
length = list.length;
for ( ; i < length; i ) {
if ( fn === list[ i ] ) {
return true;
}
}
}
return false;
},
// Remove all callbacks from the list
empty: function() {
list = [];
return this;
},
// Have the list do nothing anymore
disable: function() {
list = stack = memory = undefined;
return this;
},
// Is it disabled?
disabled: function() {
return !list;
},
// Lock the list in its current state
lock: function() {
stack = undefined;
if ( !memory || memory === true ) {
self.disable();
}
return this;
},
// Is it locked?
locked: function() {
return !stack;
},
// Call all callbacks with the given context and arguments
fireWith: function( context, args ) {
if ( stack ) {
if ( firing ) {
if ( !flags.once ) {
stack.push( [ context, args ] );
}
} else if ( !( flags.once && memory ) ) {
fire( context, args );
}
}
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 !!memory;
}
};
return self;
};
})( jQuery );

           if ( p !== name ) {

    if ( data === undefined )
    {
        return jQuery.queue( this[0], type );} 

jQuery在1.5引进了Deferred对象(异步列队),当时它还平素不分开为二个模块,放到宗旨模块中。直到1.52才分开出来。它具备七个点子:_Deferred, Deferred与when。

    clearQueue: function( type ) {

    return this.each(function(){
        var queue = jQuery.queue( this, type, data );
         if( type == "fx" && queue.length == 1 )
            queue[0].call(this);
    });
}

jQuery的when方法用于落到实处回调的回调,恐怕说,多少个异列列队都进行后才实行别的的局地回调。那么些新兴的回调也是用done, when, fail增添的,但when重返的这几个指标已经增多让客户调整它施行的本领了。因为那时候它是种叫Promise的东西,只肩负增加回调与让顾客窥探其景况。一旦前一段回调都接触了,它就自然进入正规回调列队(deferred ,见Deferred方法的定义)或错误回调列队(failDeferred )中去。但是作者那样讲,对于从未异步编制程序经验的人的话,料定听得云里雾里。看实例好了。

       // 假设data等于undefined,则以为是取队列

现今来看each方法的具体贯彻如下:

deferred = jQuery.Deferred(),
completeDeferred = jQuery.Callbacks( "once memory" ),
deferred.promise( jqXHR );
jqXHR.success = jqXHR.done;
jqXHR.error = jqXHR.fail;
jqXHR.complete = completeDeferred.add;

           type = type || "fx";

        // 在要素上发生独一的ID
        if ( !id )
            id = elem[ expando ] =  uuid; 

一向出口1,2。假若是传播多个函数,也是回来八个函数。因而对此普通的数据类型,前边的when有个别许个参数,前面包车型大巴done, fail方法的回调就有多少个参数。

           // property格式化,转变为驼峰式,因为style的属性名是驼峰式

1. 【each(callback)

jQuery.extend({
queue: function( elem, type, data ) {
if ( !elem ) {
return;
}
type = (type || "fx") "queue";
var q = jQuery.data( elem, type );
// Speed up dequeue by getting out quickly if this is just a lookup
if ( !data ) {
return q || [];
}
if ( !q || jQuery.isArray(data) ) {
q = jQuery.data( elem, type, jQuery.makeArray(data) );
} else {
q.push( data );
}
return q;
},
dequeue: function( elem, type ) {
type = type || "fx";
var queue = jQuery.queue( elem, type ), fn = queue.shift();
// If the fx queue is dequeued, always remove the progress sentinel
if ( fn === "inprogress" ) {
fn = queue.shift();
}
if ( fn ) {
// Add a progress sentinel to prevent the fx queue from being
// automatically dequeued
if ( type === "fx" ) {
queue.unshift("inprogress");
}
fn.call(elem, function() {
jQuery.dequeue(elem, type);
});
}
}
});
jQuery.fn.extend({
queue: function( type, data ) {
if ( typeof type !== "string" ) {
data = type;
type = "fx";
}
if ( data === undefined ) {
return jQuery.queue( this[0], type );
}
return this.each(function( i, elem ) {
var queue = jQuery.queue( this, type, data );
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.
//
delay: function( time, type ) {
time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;
type = type || "fx";
return this.queue( type, function() {
var elem = this;
setTimeout(function() {
jQuery.dequeue( elem, type );
}, time );
});
},
clearQueue: function( type ) {
return this.queue( type || "fx", [] );
}
});

                     start = ((end || 1) / e.cur()) * start;

if ( data !== undefined )
            jQuery.cache[ id ][ name ] = data;

deferred = jQuery.Deferred(),
completeDeferred = jQuery._Deferred(),
jqXHR ={/**/}
//....
deferred.promise( jqXHR );
jqXHR.success = jqXHR.done;
jqXHR.error = jqXHR.fail;
jqXHR.complete = completeDeferred.done;

    }

        // 完全移除成分cache
        delete jQuery.cache[ id ];
    }
}

复制代码 代码如下:

 * animate做了三件事:

return this.trigger("setData" parts[1] "!", [parts[0], value]).each(function(){jQuery.data( this, key, value );});

复制代码 代码如下:

              opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];

        // 当num不为undefined时,重临第num 1个地位极度的DOM成分
        this[ num ];
}

dojo jQuery 注解
addBoth then 同时添加正常回调与错误回调
addCallback done 添加正常回调
addErrback fail 添加错误回调
callback done 执行所有正常回调
errback reject 执行所有错误回调
doneWith 在指定作用域下执行所有正常回调,但dojo已经在addCallback上指定好了
rejectWith 在指定作用域下执行所有错误回调,但dojo已经在addErrback上指定好了
promise 返回一个外界不能改变其状态的Deferred对象(外称为Promise对象)

       for ( p in prop ) {

    return -1;
}

animate: function( prop, speed, easing, callback ) {
var empty = jQuery.isEmptyObject( prop ),
optall = jQuery.speed( speed, easing, callback ),
doAnimation = function() {
// Operate on a copy of prop so per-property easing won't be lost
var anim = Animation( this, jQuery.extend( {}, prop ), optall );
// Empty animations resolve immediately
if ( empty ) {
anim.stop( true );
}
};
return empty || optall.queue === false ?
this.each( doAnimation ) :
this.queue( optall.queue, doAnimation );
},

       }

context重回传给jQuery()的原来的DOM节点内容,即jQuery()的第4个参数。若无一点点名,那么context指向当前的文书档案(document)。

由于变量在差异功能域的集体,jQuery达成异步列队时不应用面向对象格局,它把_Deferred当作三个工厂方法,再次来到四个不透明的函数列队。之所以说不透明,是因为它的景况与成分都以闭包花招保险起来,只可以通过列队对象提供的章程开展操作。那多少个措施分别是done(加多函数),resolveWith(钦点功能域地实践全部函数),resolve(实践全数函数),isResolved(判断是不是业已调用过resolveWith或resolve方法),cancel(中断试行操作)。但_Deferred万法归宗都当做三个里边方法,从不曾经在文书档案中公然过。

果然,调用出队函数dequeue后,入队的函数根据先进先出的次第,依次被施行

dequeue: function( elem, type ){
    var queue = jQuery.queue( elem, type ),
        fn = queue.shift();
    if( !type || type === "fx" )
        fn = queue[0];
    if( fn !== undefined )
        fn.call(elem);
}

复制代码 代码如下:

8.3        完成思路
jQuery队列的完毕依据于jQuery.data,用数组完成,作为私有数量存款和储蓄在jQuery的全局变量jQuery.cache中。

  1. 【data(name)】和【data(name,value)】

  "4" : { ... },

这两性子情在上一篇文章也可能有提起,请参照他事他说加以考察jQuery.API源码深刻分析以及使用完结(2) - 对象访问和数目缓存 ,这里不再敖述。

           }

  1. 【removeData(name)】

           }

归根到底最终通过jQuery.data从jQuery.cache对象得到数据。jQuery.isArray(data) 推断是不是是新队列可能现存队列数组。

    queue: function( type, data ) {

jQuery.fn = jQuery.prototype = {
    each: function( callback, args ) {
        return jQuery.each( this, callback, args );
    }
}

                     // 计算出相对值

  1. 【selector】和【context】

                  // 开端实行动画

data(name)重返成分上囤积的应和名字的数量,能够用data(name, value)来设定。

           }, time );

例子:

 * 1. 调用jQuery.speed纠正传入的参数(时间、算法、回调函数)

末段将再次回到三个封存在 jQuery.cache[ id ][ name ] 中的数据。

5  

  1. 【size()】和【length】

  "testqueue" : [

今昔大家关切下 for ( var value = object[0]; i < length && callback.call( value, i, value ) !== false; value = object[ i] ){} 那句代码;

                     jQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&

    if ( name ) {
        // elem是不是存在成分cache
        if ( jQuery.cache[ id ] ) {
            // 移除四个享有特定键的因素数据
            delete jQuery.cache[ id ][ name ]; 

    // Based off of the plugin by Clint Helfers, with permission.

  1. 【get()】和【get(index)】

              // 不是数值型

因此调用 delete jQuery.cache[ id ][ name ];  和 delete jQuery.cache[ id ];,移除全体该因素上的cache数据;

    return this[ optall.queue === false ? "each" : "queue" ](function() {

个中那句代码

           parts, start, end, unit;

  1. 【dequeue([name])】

           // Add a progress sentinel to prevent the fx queue from being

后续打开jQuery.removeData方法的切实可行达成:

              }

这四个都以收获jQuery 对象瓜时素的个数,具体达成如下:

                  // 要是以 =/-=最早,则做相对动画

乐百家前段,function now(){
    return  new Date;
}
var expando = "jQuery"   now(), uuid = 0, windowData = {}; 

    // queue( [ queueName ] )

    return ret;
}

    (function () {alert(2);}),

我们看下jQuery.data(this,key,value);那句代码,继续展开jQuery.data方法的求实达成以及有关其余代码:

宣示:本文为原创作品,如需转发,请阐明来源并保留原版的书文链接。

好了,jQuery对象访谈和数码缓存的原理机制正是那般的。

           if ( count ) {

    if( array != null ){
        var i = array.length;
        // The window, strings (and functions) also have 'length'
        if( i == null || typeof array === "string" || jQuery.isFunction(array) || array.setInterval )
            ret[0] = array;
        else
            while( i )
                ret[--i] = array[i];
    } 

    // Do not change referenced properties as per-property easing will be lost

是因为div节点产生动画效果,每条动画就调用三个jQuery.data方法,将每条动作保存在jQuery.cache中,就形成了缓存队列。至于div节点产生动画效果怎样调用jQuery.data方法会在之后的章节中介绍。

    n  全体队列名会自动抬高queue后缀,表示那是贰个行列

当大家要在要素上寄放数据的时候,比方 $("div").data("blah","hello"); 将实行那句代码:

              // 倘使不是toggle,表达val是hide/show之一

其中object[0]赢得jQuery对象中的第多个DOM成分,通过for循环,获得遍历整个jQuery对象中对应的每一种DOM成分,通过callback.call( value,i,value); 将callback的this对象指向value对象,並且传递四个参数,i表示索引值,value表示DOM成分;个中callback是近似于 function(index, elem) { ... } 的诀窍。所以就得到$("...").each(function(index, elem){ ... });

              queue.unshift("inprogress");

其中 if(typeof type !== "string") { data = type; type = "fx"; } 能够得出fx为暗中同意的连串名称。继续查看jQuery.queue方法:

8.2        用途
在jQuery源码中,仅用于动画模块,这里入队的函数的作用是:

    } else {
        // Clean up the element expando
        try {
            delete elem[ expando ];
        } catch(e){
            // IE has trouble directly removing the expando
            // but it's ok with using removeAttribute
            if ( elem.removeAttribute )
                elem.removeAttribute( expando );
        } 

  1. 队列 Queue
    8.1        概述
    队列是一种新鲜的线性表,只同目的在于表的前端(队头)举行删减操作(出队),在表的后端(队尾)举办扦插操作(入队)。队列的性状是先进先出(FIFO-first in first out),即首先插入的因素最初被去除。

当大家供给重回成分上囤积的对应名字的多寡的时候,举个例子$("div").data("blah"); 重要将实施这句代码:

 * 3. 遍历要动画的质量,为每八个属性创设jQuery.fx对象,计算开头值和终止值,调用fx对象的custom早先动画

如今看下get方法的现实落实如下:

           // 若是动画实行达成(即不是inprogress),则从队列底部移除

data = jQuery.data( this[0], key );

       var opt = jQuery.extend( {}, optall ), // 复制一份

  1. 【index(subject)】 

           // 2. 允许为默写属性钦定算法

 

 */

get: function( num ) {
    return num === undefined ? 

$.expando有三有个别构成:字符串"jQuery" 版本号jQuery.fn.jquery 随机数Math.random(),因而老是加载页面后都不雷同。

分析

           fn = queue.shift(), // 收取第二个

removeData: function( key ){
    return this.each(function(){
        jQuery.removeData( this, key );
    });
}

前记:

 

command: >>> $('body')[0][$.expando]

$('body').queue( 'test', function(){ alert(1); } )

当包含num时,直接回到 this[ num ],所以那样表明了 $(this).get(0)与$(this)[0]等价 的说明。

国庆给自个儿放了个安静的长假,日游大阪大小景点,夜宿玄武湖边上,于三街六巷中遍尝美味小吃,未有Computer未有互联网,那样的生活真是是好日子啊;回京开始专门的工作了,编程是自己的兴趣,尽管产生了劳作,不过享受的激情要承接接保险持下去。

一、jQuery对象访谈

                  if ( parts[1] ) {

    return object;
}

    prop = jQuery.extend( {}, prop );

前几日来看看data方法的切切实实贯彻:

       if ( elem ) {

selector重返传给jQuery()的固有选拔器。

              } else {

makeArray: function( array ) {
    var ret = []; 

       }

例子

       if ( optall.queue === false ) {

再看第二行的例子,queue的率先个参数为二个函数,当实践完那一个自定义函数后,要继续执行队列,那要调用dequeue方法。

    // 重临在钦点的成分element上将在实施的函数队列

        if ( value === undefined ) {
            var data = this.triggerHandler("getData"   parts[1]   "!", [parts[0]]); 

       }

get(index)获得当中三个一双两好的DOM成分,index表示收获第多少个门道卓越的成分。

 

从队列最前端移除贰个体系函数,并实行它。

           // 如果是toggle/show/hide,

        // 幸免贰个undefined的值覆盖jQuery.cache对象
        if ( data !== undefined )
            jQuery.cache[ id ][ name ] =**
 data;** 

           // display

jQuery.extend({
    cache: {},     data: function( elem, name, data ) {
        elem = elem == window ?
            windowData :
            elem; 

                     // block-level elements need to be inline with layout

近日看下index方法的有血有肉落到实处如下:

l  调用jQuery.queue入队时,倘使不传入队列名,则默以为fx(规范动画)

        if ( !q || jQuery.isArray(data) )
            q = jQuery.data( elem, type, jQuery.makeArray(data) );
        else if( data )
            q.push( data ); 

           }

            return data === undefined && parts[1] ?
                this.data( parts[0] ) :
                data;
        } else
            return this.trigger("setData"   parts[1]   "!", [parts[0], value]).each(function(){
                jQuery.data( this, key, value );
            });
    }, 

              opt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';

        var id = elem[ expando ]; 

 

找出与参数表示的对象相配的因素,并再次来到相应成分的索引值。

           queueDataKey = type "queue",

get()取得富有相配的 DOM 成分集结。

       if ( typeof type !== "string" ) {

能够看看这里的array为jQuery对象,由此实行 while( i ) ret[--i] = array[i]; , 重临的是以array全数相配的DOM成分所组成的数组。那和前边的定义相平等。

    // 复制一份prop,不更换原本的属性

乐百家前段 1 乐百家前段 2 

作者:nuysoft/高云 QQ:47214707 EMail:[email protected]

            for ( name in jQuery.cache[ id ] )
                break; 

              // 假如是toggle,则判别当前是还是不是hidden,假诺hidden则show,不然hide

        // 当num为undefined时,重返全数相称的DOM成分集结
        jQuery.makeArray( this ) : 

    //

    if ( args ) {
        if ( length === undefined ) {
            for ( name in object )
                if ( callback.apply( object[ name ], args ) === false )
                    break;
        } else
            for ( ; i < length; )
                if ( callback.apply( object[ i  ], args ) === false )
                    break; 
    // 以下是客商端程序实行调用
    } else {
        if ( length === undefined ) {
            for ( name in object )
                if ( callback.call( object[ name ], name, object[ name ] ) === false )
                    break;
        } else
            for ( var value = object[0];
                i < length && callback.call( value, i, value ) !== false; value = object[ i] ){}
    } 

    // 调用jQuery.data,存款和储蓄为个中数据(pvt为true)

将data存储在cache对象中。

    // 清空队列,通过将第二参数设置为空数组[]

dequeue的实际落成为:

       // elem务必存在,不然未有意义

    return jQuery.inArray(
        // 假设elem为多个jQuery对象,那么获得的是率先个相当的DOM成分
        elem && elem.jquery ? elem[0] : elem
    , this );
}

 

请看率先行的事例,能够看到这里包蕴7条动效,也正是在还从未执行它们以前,假如调用 var n = $("div").queue("fx"); 再次来到贰个队列对象n,查看该目的的长短,发掘队列长度为7,而每实践完一条动作,队列长度就能够减1。

       // test suite

HTML代码 jQuery代码
<div></div>

$("div").data("blah"); // undefined
$("div").data("blah", "hello"); // blah设置为hello
$("div").data("blah"); // hello
$("div").data("blah", 86); // 设置为86
$("div").data("blah"); // 86
$("div").removeData("blah"); //移除blah
$("div").data("blah"); // undefined

<div></div>

$("div").data("test", { first: 16, last: "pizza!" });
$("div").data("test").first //16;
$("div").data("test").last //pizza!;

           }

HTML 代码 jQuery 代码
  <style>
        div { margin:3px; width:40px; height:40px;
        position:absolute; left:0px; top:30px;
        background:green; display:none; }
        div.newcolor { background:blue; }
        span { color:red; }
        </style>
        <button id="show">Show Length of Queue</button>
        <span></span>
        <div></div>
$("#show").click(function () {
        var n = $("div").queue("fx");
        $("span").text("Queue length is: "   n.length);
        });
        function runIt() {
        $("div").show("slow");
        $("div").animate({left:' =200'},2000);
        $("div").slideToggle(1000);
        $("div").slideToggle("fast");
        $("div").animate({left:'-=200'},1500);
        $("div").hide("slow");
        $("div").show(1200);
        }
        runIt();
  <style>
        div { margin:3px; width:40px; height:40px;
        position:absolute; left:0px; top:30px;
        background:green; display:none; }
        div.newcolor { background:blue; }
        </style>
        Click here...
        <div></div>
$(document.body).click(function () {
        $("div").show("slow");
        $("div").animate({left:' =200'},2000);
        $("div").queue(function () {
        $(this).addClass("newcolor");
        $(this).dequeue();
        });
        $("div").animate({left:'-=200'},500);
        $("div").queue(function () {
        $(this).removeClass("newcolor");
        $(this).dequeue();
        });
        $("div").slideUp();
        });
  <style>
        div { margin:3px; width:40px; height:40px;
        position:absolute; left:0px; top:30px;
        background:green; display:none; }
        div.newcolor { background:blue; }
        </style>
        <button id="start">Start</button>
        <button id="stop">Stop</button>
        <div></div>
  $("#start").click(function () {
        $("div").show("slow");
        $("div").animate({left:' =200'},5000);
        $("div").queue(function () {
        $(this).addClass("newcolor");
        $(this).dequeue();
        });
        $("div").animate({left:'-=200'},1500);
        $("div").queue(function () {
        $(this).removeClass("newcolor");
        $(this).dequeue();
        });
        $("div").slideUp();
        });
          $("#stop").click(function () {
        $("div").queue("fx", []);
        $("div").stop();
        });

调节台命令
 $('body').dequeue( 'test' )
 $('body').dequeue( 'test' )
 $('body').dequeue( 'test' )
 
浏览器截图
 见附件PDF  见附件PDF  见附件PDF 
队列长度
 2
 1
 0  

        return name ?
            jQuery.cache[ id ][ name ] :
            id;
    }
});

    }

index: function( elem ) { 

       }

能够看来它回到的是大局的each方法,而且将自个儿jQuery对象做为参数给它,全局的each方法的求实完毕如下:

寻访源码:

接轨翻看jQuery.inArray方法,具体落到实处如下:

  "3" : { ... },

HTML代码 jQuery代码 运行结果
<img/><img/>

$("img").each(function(i){
   this.src = "test" i ".jpg";
});

[ <img src="test0.jpg" />, <img src="test1.jpg" /> ]
<img/><img/>

$("img").each(function(){
  $(this).toggleClass("example");
});

切换样式example

                  // 队列存在的话,且data不是数组,直接入队

前言

    delay: function( time, type ) {

    var id = elem[ expando ]; 

           // 能够看到fn必得是函数,不然会出错

            // 将键值置空,盘算移除成分cache
            name = ""; 

  "1" : { ... },

queue: function(type, data){
    if ( typeof type !== "string" ) {
        data = type;
        type = "fx";
    } 

           } else {

当今拜望queue的切实落到实处:

                  if ( unit !== "px" ) {

                  jQuery.data( elements[ i ], deferDataKey, jQuery._Deferred(), true ) )) {

           display, e,

       time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;

              handleQueueMarkDefer( elem, type, "mark" );

           // 1. 同目的在于某个品质还未成功时就实行回调函数、实践下八个卡通

 

           }

       return true;

                         this.style.zoom = 1;

              defer.resolveWith( elements, [ elements ] );

                     jQuery.css( this, "float" ) === "none" ) {

    // jQuery.queue( element, [queueName] )

undefined  

    n  入队的因素必得是函数,或由函数构成的数组

                     end = ( (parts[ 1 ] === "-=" ? -1 : 1) * end ) start;

                     jQuery.style( this, p, start unit);

       });

           object = type;

本文由乐百家前段发布,转载请注明来源:jquery1.83 从前全体与异步列队相关的模块详细介绍