$.queue是jquery里面的一种队列,在动画里面用的比较多,也可以单独使用,今天看看这个是怎么玩的。

$.queue

这是一个挂在$全局方法上的一个添加队列的方式,例如:

注意,上面的代码内部采用的是$._data在obj对象上挂载了名为aqueue的队列('a'+'queue'),和aqueueHooks的$.Callback('a'+'queueHooks')。

$.Callback中装的是等队列完成后的回调方法,这个可以add多个的,具体的$.Callback使用,可以看 $.Callback使用

$.dequeue

这个方法是对应$.queue的触发方法,我们接着上面的demo,看看如何触发自定义的队列:

我们可以看到,我们在obj上建立了一个名为'aqueue'的队列,然后在队列里面放入了两个方法,同时,每个方法在调用的时候,在'aqueueHooks'里面都添加了一个回调,如下图:

background Layer 1 var obj={'name':'nb'} var f1=function(next,hook){hook.empty.add(f3);} var f2=function(next,hook){hook.empty.add(f4);} $.queue(obj,'a',f1); $.queue(obj,'a',f2); aqueue f1 f2 aqueueHooks f3 f4 a队列 obj aqueue执行完 后执行aqueueHooks

注意,aqueue是一个队列,遵从先入先出的规则;aqueueHooks是一个$.Callback,会按照顺序执行add进入的方法。在队列里面是先把队列所有执行完才会调用到$.Callback里面的内容。

每执行一个dequeue,其实就相当于从队列中出列一个。我们看上面的demo会发现,队列里面只有两个元素,为什么dequeue三次?因为最后一次是触发$.Callback的,我们先看以下$.dequeue的源码:

我们可以发现,只有当前的队列里面是空的才会触发$.Callback,因此要多dequeue一次。

我们可以合理的利用next(next其实相当于dequeue),然后队列只需要dequeue一次,后面自动连起来,就像鞭炮一样,一旦引燃了,后面就自动点燃,代码如下:

我们可以看到,队列中最后一个方法执行next为的是执行接下来的$.Callback。

还有一点要注意,如果是用'fx'作为队列名,那么在dequeue的时候可以不用指定是哪个队列,因为'fx'是默认队列名,直接$.dequeue(obj)就好了。

$.fn.queue

这个和$.queue不同就是这个要配合元素一起使用,例如$(el).queue(name,fn)。不过在内部实现上,$.queue和$.fn.queue还是有区别的,我们先来看看下面的例子:

如果不是很了解内部逻辑还真的说不上来有什么不同,其实这两者最大的不同就是绑定的对象不同:

background Layer 1 $.queue($('div').eq(0),'a',f1); aqueue f1 aqueueHooks a队列 [<div></div>] aqueue执行完 后执行aqueueHooks $('div').eq(0).data('b',f1); aqueue f1 aqueueHooks a队列 <div></div> $('div').eq(0)返回的是一个数组,所以队列其实是绑定在了这个返回的数组上了 $('div').eq(0).data('b',f1)绑定的是每个真正的元素上了

也就是说$.queue($('div').eq(0),'a',f1);根本没有把队列绑定在$('div').eq(0)这个真正的对象上,而是绑定在了$('div').eq(0)返回这个数组上了!

如果想让$.queue绑定到具体的DOM元素上,可以这样:$.queue($('div').eq(0)[0],'a',f1),如下图所示:

$.animate中也有使用队列,它使用的是默认队列'fx',我们可以指定其他的队列名,用dequeue触发,或者不使用队列,具体请看下面的demo:

我们可以发现如果$.animate不使用队列,那么多个动画是同时进行的。

$.fn.delay

这个是延迟队列执行的,简单demo如下:

这个就好比在队列中放了一个延迟执行dequeue的方法。看看delay的源代码:

background Layer 1 var $div=$('div').eq(0); aqueue f1 aqueueHooks <div></div> 暂停1s $div.delay(1000,'a'); $div.dequeue(1000,'a',f1);

可以发现其实delay的就是延迟执行了dequeue而已。

$.fn.promise

这个就比较厉害了,通过刚刚我们知道,给一个对象上添加一个队列,可以通过hooks添加回调方法,但是如果同时有很多对象都有队列,那么如何知道最后一个队列完成呢?这就是promise做的,我们先来看一个demo:

promise其实是吧所有的队列中的hooks里面添加了一个检查是否所有队列完成的一个方法,然后自己返回的是一个Deferred对象的promise方法。只要所有的执行完毕,那么就会执行Deferred后面添加then或者done方法。$.Deferred的使用可以看: $.Deferred源码分析

background Layer 1 $('.unit').each(function(i,n){ $(this).delay(i*1000).fadeIn(500).fadeOut(500) }); $('.unit').promise().done(f1); fxqueue fadeIn fxqueueHooks check 第一个unit fadeOut f1 promise的Deferred对象 check方法是promise添加到每个队列hooks里面的一个检查方法 一旦监测到所有队列执行完毕,执行promise返回的Deferred对象后面添加的方法。 fxqueue fadeIn fxqueueHooks check 第二个unit fadeOut 暂停1s fxqueue fadeIn fxqueueHooks check 第三个unit fadeOut 暂停2s resolve队列 reject队列 progress队列 resolve reject notify

看看promise的源码就知道了:

如果说promise的对象没有队列怎么办?那么promise返回的Deferred对象就会立即执行,例如:

其他文章

0
我要评论

评论

返回
×

我要评论

回复:

昵称:(昵称不超过20个字)

图片:

提交
还可以输入500个字