读jQuery之二十一(队列queue)

queue模块在jQuery中分在Effects中,搜索整个库会发现queue也仅在特效模块effects.js中被使用。jQuery抽取出独立的命名空间给queue,说明除了内部Effects模块使用外,客户端程序员可以充分发挥聪明才智使用queue来构建非动画API。

queue模块向外开放的API分别是

  • 挂在$上的$.queue、$.dequeue、$._queueHooks(仅内部)
  • 挂在jQuery对象上的有queue、dequeue、delay、clearQueue、promise

 

按照jQuery的惯例,挂在$上的方法属于低级API,挂在jQuery对象上的才是经常使用的。

一般低级API是为高级API服务的,即 queue内部会使用$.queue, dequeue内部会使用$.dequeue。这里实际是实现为一个队列,$.queue是入列,$.dequeue是出列。

 

一、$.queue

这个方法有两个作用,它既是setter,又是getter。第一个参数elem是DOM元素,第二个参数type是字符串,第三个参数data可以是function或数组。

1. 设置指定名字的queue

?
1
2
3
4
5
6
function  cb1() {alert(1)}
function  cb2() {alert(2)}
var  arr = [cb1, cb2];
 
$.queue(el, 'mx' , cb1); // 第三个参数为function
$.queue(el, 'xm' , arr); // 第三个参数为数组

 

2. 这时可以取到存入的callbacks

?
1
2
var  cbs1 = $.queue(el, 'mx' ); // [cb1]
var  cbs2 = $.queue(el, 'xm' ); // [cb1, cb2]

 

$.queue内部使用 $._data方法,将数据保存下来。默认type/queueName使用  "fx" + queue。$.queue的实现很简单,代码不过15行,即取缓存对象queue,如果不存在则初始化为一个空对象,然后将data存入,如果存在则直接将data push到数组中。

 

二、$.dequeue 

将回调函数出列执行,每调用一次仅出列一个,因此当回调有N个时,需要调用$.dequeue方法N次元素才全部出列。$.dequeue的第一个参数是dom元素,第二个参数是queueName

?
1
2
3
4
5
6
7
8
9
10
11
12
13
function  ff1() {console.log(1)}
function  ff2() {console.log(2)}
function  ff3() {console.log(3)}
 
var  p = $( 'p' )[0];
$.queue(p, 'mx1' , ff1);
$.queue(p, 'mx1' , ff2);
$.queue(p, 'mx1' , ff3);
 
// 每2秒调用一次$.dequeue,依次输出1,2,3
setInterval( function () {
     $.dequeue(p, 'mx1' )
}, 2000);

 回调函数的上下文是dom元素,参数是next函数和hooks对象

?
1
2
3
4
5
6
7
8
var  p = $( 'p' )[0];
function  func(next, hooks) {
    console.log( this );
    console.log(next);
    console.log(hooks);
}
$.queue(p, 'mx' , func);
$.dequeue(p, 'mx' ); // p, function, [object Object]

 

next内部仍然调用$.dequeue,这样可以接着执行队列中的下一个callback。$.dequeue里的hooks是当队列里所有的callback都执行完后(此时startLength为0)进行最后的一个清理工作,

?
1
2
3
if  ( !startLength && hooks ) {
     hooks.empty.fire();
}

hooks.empty是一个jQuery.Callbacks对象,而它则是定义在$._queueHooks里

?
1
2
3
4
5
6
7
8
9
_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"  );
             jQuery._removeData( elem, key );
         })
     });
}

 

以上就是queue的全部了,本质是利用Array的push和shift来完成先进先出(First In First Out),但这里有个缺陷,jQuery的queue从1.1开始就是为effects模块服务的,因此queue里存的都是function。个人觉得如果只存function,应该对data参数做个严格类型判断,如果不是function则抛异常。但目前的版本没有做严格判断,如果我存的不是function,这样dequeue时会报错。如下

?
1
2
3
var  p = $( 'p' )[0];
$.queue(p, 'mx1' , {}); // 注意第三个参数是对象,非function
$.dequeue(p, 'mx1' ); // fn.call 报错,因为fn不是function

 

三、queue

知道了$.queue,queue就很好理解了,它无非是内部调用了下$.queue。queue比$.queue 少了第一个参数,内部使用this代替第一个参数。

?
1
2
3
4
5
6
7
8
function  ff1() {console.log(1)}
function  ff2() {console.log(2)}
function  ff3() {console.log(3)}
 
var  $p = $( 'p' );
$p.queue( 'mx' , ff1);
$p.queue( 'mx' , ff2);
$p.queue( 'mx' , ff3);

这样,三个function就入列了,列名是"mx"。 取队列元素只需传一个列名如"mx"

?
1
var  queue = $p.queue( 'mx' ); // [ff1, ff2, ff3]

 

还有个技巧就是,如果使用jQuery默认的队列"fx",可以只传data

?
1
2
3
4
5
6
7
function  ff1() {console.log(1)}
function  ff2() {console.log(2)}
function  ff3() {console.log(3)}
var  $p = $( 'p' );
$p.queue(ff1);
$p.queue(ff2);
$p.queue(ff3);

另外一点,当使用默认列名"fx"时,它会调用$.dequeue出列执行下,源码如下

?
1
2
3
if  ( type === "fx"  && queue[0] !== "inprogress"  ) {
     jQuery.dequeue( this , type );
}

 

四、dequeue

dequeue则更是未添加任何特殊处理,直接调用的$.dequeue,见源码

?
1
2
3
4
5
dequeue: function ( type ) {
     return  this .each( function () {
         jQuery.dequeue( this , type );
     });
},

 

五、delay

delay用来延迟后续添加的callback的执行,第一个参数time是延迟时间(另可使用"slow"和"fast"),第二个是队列名。

?
1
2
3
4
5
6
7
function  cb() {
     console.log(1);   
}
var  $p = $( 'p' );
$p.delay(2000, 'mx' ).queue( 'mx' , cb);
 
$p.dequeue( 'mx' ); // 2秒后输出1

如果是这样

?
1
2
3
4
5
6
7
8
9
10
function  ff1() {console.log(1)}
function  ff2() {console.log(2)}
 
var  $p = $( 'p' );
$p.queue( 'mx' , ff1);
$p.delay(4000, 'mx' );
$p.queue( 'mx' , ff2);
 
$p.dequeue( 'mx' ); // 立即输出1
$p.dequeue( 'mx' ); // 4秒后输出2

 

六、clearQueue

顾名思义,清空所有队列。没什么好说的,源码如下,直接使用一个空数组覆盖之前的数组队列了。

?
1
2
3
clearQueue: function ( type ) {
     return  this .queue( type || "fx" , [] );
},

  

七、promise

这个方法返回一个promise对象,promise对象既是前面提到的Deferred对象的阉割版。你可以使用done、fail、progress添加,但不能触发。用在queue模块里有特殊意义,比如done它指queue里所有function都执行后才执行done添加的。如

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function  ff1() {
     alert(1)
}
function  ff2() {
     alert(2)
}
function  succ() {
     alert( 'done' )
}
$body = $( 'body' )
$body.queue( 'mx' , ff1);
$body.queue( 'mx' , ff2);
 
var  promise = $body.promise( 'mx' );
promise.done(succ);
 
setInterval( function () {
     $body.dequeue( 'mx' ) // 先弹出1,2,最后是"done"
}, 1500)

 <script type="text/javascript"> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值