• 读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

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

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

    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

    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对象

    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)进行最后的一个清理工作,

    if ( !startLength && hooks ) {
    	hooks.empty.fire();
    }
    

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

    _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时会报错。如下

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

    三、queue

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

    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"

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

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

    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出列执行下,源码如下

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

    四、dequeue

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

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

    五、delay

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

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

    如果是这样

    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

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

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

      

    七、promise

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

    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)
    

    注:阅读版本为1.9.1

  • 相关阅读:
    ajax的原理及实现方式
    在linux中添加环境变量
    ftp简单命令
    linux命令之scp
    java中创建对象的方法
    10个调试技巧
    java读取.properties配置文件的几种方法
    Java对象和XML转换
    Java Float类型 减法运算时精度丢失问题
    Java内存分配全面浅析
  • 原文地址:https://www.cnblogs.com/snandy/p/2892749.html
Copyright © 2020-2023  润新知