jQuery 中的队列是啥?

Posted

技术标签:

【中文标题】jQuery 中的队列是啥?【英文标题】:What are queues in jQuery?jQuery 中的队列是什么? 【发布时间】:2010-11-06 16:30:14 【问题描述】:

我发现queue()/dequeue() 上的 jQuery.com 文档太简单了,难以理解。 jQuery 中的队列到底是什么?我应该如何使用它们?

【问题讨论】:

解决队列问题的一个很好的例子:***.com/questions/5230333/… 【参考方案1】:

它允许您将动画排队...例如,而不是这个

$('#my-element').animate(  opacity: 0.2, width: '100px' , 2000);

同时淡化元素并使宽度变为 100 像素。使用队列可以让您暂存动画。所以一个接一个地完成。

$("#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);
    $("div").slideUp("normal", runIt);

runIt();

来自http://docs.jquery.com/Effects/queue的示例

【讨论】:

这是不正确的。当您有多个“动画”调用时,jQuery 会将它们放入队列中以逐个执行它们。使用 queue 方法,现在您可以访问该队列并在需要时对其进行操作。 @SolutionYogi - 如果您认为我的答案不正确,请编辑我的答案 - 答案是 CW'd 并且您有足够的代表。【参考方案2】:

要了解队列方法,你必须了解 jQuery 是如何做动画的。如果您一个接一个地编写多个动画方法调用,jQuery 会创建一个“内部”队列并将这些方法调用添加到其中。然后它会一一运行这些动画调用。

考虑以下代码。

function nonStopAnimation()

    //These multiple animate calls are queued to run one after
    //the other by jQuery.
    //This is the reason that nonStopAnimation method will return immeidately
    //after queuing these calls. 
    $('#box').animate( left: '+=500', 4000);
    $('#box').animate( top: '+=500', 4000);
    $('#box').animate( left: '-=500', 4000);

    //By calling the same function at the end of last animation, we can
    //create non stop animation. 
    $('#box').animate( top: '-=500', 4000 , nonStopAnimation);

'queue'/'dequeue' 方法让您可以控制这个“动画队列”。

默认情况下,动画队列名为“fx”。我在这里创建了一个示例页面,其中包含各种示例,这些示例将说明如何使用队列方法。

http://jsbin.com/zoluge/1/edit?html,output

以上示例页面的代码:

$(document).ready(function() 
    $('#nonStopAnimation').click(nonStopAnimation);

    $('#stopAnimationQueue').click(function() 
        //By default all animation for particular 'selector'
        //are queued in queue named 'fx'.
        //By clearning that queue, you can stop the animation.
        $('#box').queue('fx', []);
    );

    $('#addAnimation').click(function() 
        $('#box').queue(function() 
            $(this).animate( height : '-=25', 2000);
            //De-queue our newly queued function so that queues
            //can keep running.
            $(this).dequeue();
        );
    );

    $('#stopAnimation').click(function() 
        $('#box').stop();
    );

    setInterval(function() 
        $('#currentQueueLength').html(
         'Current Animation Queue Length for #box ' + 
          $('#box').queue('fx').length
        );
    , 2000);
);

function nonStopAnimation()

    //These multiple animate calls are queued to run one after
    //the other by jQuery.
    $('#box').animate( left: '+=500', 4000);
    $('#box').animate( top: '+=500', 4000);
    $('#box').animate( left: '-=500', 4000);
    $('#box').animate( top: '-=500', 4000, nonStopAnimation);

现在你可能会问,我为什么要打扰这个队列?通常情况下,你不会。但是如果你有一个复杂的动画序列想要控制,那么队列/出队方法是你的朋友。

另请参阅 jQuery 组上有关创建复杂动画序列的有趣对话。

http://groups.google.com/group/jquery-en/browse_thread/thread/b398ad505a9b0512/f4f3e841eab5f5a2?lnk=gst

动画演示:

http://www.exfer.net/test/jquery/tabslide/

如果您还有问题,请告诉我。

【讨论】:

【参考方案3】:

jQuery.queue().dequeue()的使用

jQuery 中的Queues 用于动画。您可以将它们用于您喜欢的任何目的。它们是一个函数数组,使用jQuery.data() 按元素存储。它们是先进先出 (FIFO)。您可以通过调用.queue() 将函数添加到队列中,然后使用.dequeue() 删除(通过调用)函数。

要了解内部 jQuery 队列函数,reading the source 并查看示例对我有很大帮助。我见过的队列函数的最佳示例之一是.delay()

$.fn.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 );
  );
;

默认队列 - fx

jQuery 中的默认队列是fx。默认队列具有一些不与其他队列共享的特殊属性。

    自动启动:当调用$(elem).queue(function());时,fx队列会自动dequeue下一个函数,如果队列没有启动则运行它。 'inprogress' sentinel: 每当你dequeue() 来自fx 队列的函数时,它会unshift()(推入数组的第一个位置)字符串"inprogress" - 它标记队列当前正在运行。 这是默认设置!fx 队列由 .animate() 以及默认调用它的所有函数使用。

注意:如果你使用自定义队列,你必须手动.dequeue()函数,它们不会自动启动!

检索/设置队列

您可以通过不带函数参数调用.queue() 来检索对jQuery 队列的引用。如果您想查看队列中有多少项目,可以使用该方法。您可以使用pushpopunshiftshift 来操作队列。您可以通过将数组传递给.queue() 函数来替换整个队列。

快速示例:

// lets assume $elem is a jQuery object that points to some element we are animating.
var queue = $elem.queue();
// remove the last function from the animation queue.
var lastFunc = queue.pop(); 
// insert it at the beginning:    
queue.unshift(lastFunc);
// replace queue with the first three items in the queue
$elem.queue(queue.slice(0,3)); 

动画 (fx) 队列示例:

Run example on jsFiddle

$(function() 
    // lets do something with google maps:
    var $map = $("#map_canvas");
    var myLatlng = new google.maps.LatLng(-34.397, 150.644);
    var myOptions = zoom: 8, center: myLatlng, mapTypeId: google.maps.MapTypeId.ROADMAP;
    var geocoder = new google.maps.Geocoder();
    var map = new google.maps.Map($map[0], myOptions);
    var resized = function() 
        // simple animation callback - let maps know we resized
        google.maps.event.trigger(map, 'resize');
    ;

    // wait 2 seconds
    $map.delay(2000);
    // resize the div:
    $map.animate(
        width: 250,
        height: 250,
        marginLeft: 250,
        marginTop:250
    , resized);
    // geocode something
    $map.queue(function(next) 
        // find ***'s whois address:
      geocoder.geocode('address': '55 Broadway New York NY 10006',handleResponse);

      function handleResponse(results, status) 
          if (status == google.maps.GeocoderStatus.OK) 
              var location = results[0].geometry.location;
              map.setZoom(13);
              map.setCenter(location);
              new google.maps.Marker( map: map, position: location );
          
          // geocoder result returned, continue with animations:
          next();
      
    );
    // after we find stack overflow, wait 3 more seconds
    $map.delay(3000);
    // and resize the map again
    $map.animate(
        width: 500,
        height: 500,
        marginLeft:0,
        marginTop: 0
    , resized);
);

另一个自定义队列示例

Run example on jsFiddle

var theQueue = $(); // jQuery on an empty object - a perfect queue holder

$.each([1,2,3],function(i, num) 
  // lets add some really simple functions to a queue:
  theQueue.queue('alerts', function(next)  
    // show something, and if they hit "yes", run the next function.
    if (confirm('index:'+i+' = '+num+'\nRun the next function?')) 
      next();
    
  ); 
);

// create a button to run the queue:
$("<button>", 
  text: 'Run Queue', 
  click: function()  
    theQueue.dequeue('alerts'); 
  
).appendTo('body');

// create a button to show the length:
$("<button>", 
  text: 'Show Length', 
  click: function()  
    alert(theQueue.queue('alerts').length); 
  
).appendTo('body');

排队 Ajax 调用:

我开发了一个$.ajaxQueue() 插件,它使用$.Deferred.queue()$.ajax() 还传回了一个promise,该promise 在请求完成时被解析。 $.ajaxQueue 的另一个版本在 1.4 中仍然有效,发布在我对 Sequencing Ajax Requests 的回答中

/*
* jQuery.ajaxQueue - A queue for ajax requests
* 
* (c) 2011 Corey Frang
* Dual licensed under the MIT and GPL licenses.
*
* Requires jQuery 1.5+
*/ 
(function($) 

// jQuery on an empty object, we are going to use this as our Queue
var ajaxQueue = $();

$.ajaxQueue = function( ajaxOpts ) 
    var jqXHR,
        dfd = $.Deferred(),
        promise = dfd.promise();

    // queue our ajax request
    ajaxQueue.queue( doRequest );

    // add the abort method
    promise.abort = function( statusText ) 

        // proxy abort to the jqXHR if it is active
        if ( jqXHR ) 
            return jqXHR.abort( statusText );
        

        // if there wasn't already a jqXHR we need to remove from queue
        var queue = ajaxQueue.queue(),
            index = $.inArray( doRequest, queue );

        if ( index > -1 ) 
            queue.splice( index, 1 );
        

        // and then reject the deferred
        dfd.rejectWith( ajaxOpts.context || ajaxOpts,
            [ promise, statusText, "" ] );

        return promise;
    ;

    // run the actual query
    function doRequest( next ) 
        jqXHR = $.ajax( ajaxOpts )
            .done( dfd.resolve )
            .fail( dfd.reject )
            .then( next, next );
    

    return promise;
;

)(jQuery);

我现在已将此作为文章添加到 learn.jquery.com,该网站上还有其他关于队列的精彩文章,去看看。

【讨论】:

+1。我正在开发一个基于 jQuery 的用户脚本,它需要连接到 php 脚本,就好像它是在客户端上运行的另一个 PHP 脚本一样——一次一个 HTTP 请求/其他操作,所以这肯定会有所帮助。只是一个问题:jQuery 要求将队列附加到对象,对吗?那么我应该使用哪个对象? $(window)? @idealmachine - 如 Ajax 队列示例中所示,您实际上可以将队列事件附加到一个空对象:$() 这个总结非常有用。我刚刚构建了一个惰性加载器,用于延迟对屏幕底部下方的大量内容的请求,直到它滚动到视图中。使用 jQuery 的 queue() 使这些 Ajax 请求非常流畅(即使您直接跳到页面底部)。谢谢! 很高兴发现您仍在为更新版本的 jQuery 更新此内容。 +1 :) 为那些刚刚学习队列和承诺等的人添加一件事 - 在 ajaxQueue 示例中,对 $.ajaxQueue() 的调用将您希望在 () 中排队的 ajax 请求放入其中回报一个承诺。等待队列为空的方法是通过 promise.done(function() alert("done"));。我花了一个小时才找到这个,所以希望这可以帮助其他人节省他们的时间!【参考方案4】:

这个帖子对我的问题有很大帮助,但我以不同的方式使用了 $.queue,我想我会在这里发布我想出的东西。我需要的是要触发的一系列事件(帧),但要动态构建的序列。我有可变数量的占位符,每个占位符都应该包含一个动画图像序列。数据保存在一个数组数组中,所以我循环遍历数组为每个占位符构建每个序列,如下所示:

/* create an empty queue */
var theQueue = $();
/* loop through the data array */
for (var i = 0; i < ph.length; i++) 
    for (var l = 0; l < ph[i].length; l++) 
        /* create a function which swaps an image, and calls the next function in the queue */
        theQueue.queue("anim", new Function("cb", "$('ph_"+i+"' img').attr('src', '/images/"+i+"/"+l+".png');cb();"));
        /* set the animation speed */
        theQueue.delay(200,'anim');
    

/* start the animation */
theQueue.dequeue('anim');

这是我得到的脚本的简化版本,但应该显示原理 - 当一个函数添加到队列中时,它是使用 Function 构造函数添加的 - 这样可以使用来自的变量动态编写函数循环。注意函数传递参数的方式 next() 调用,并在最后调用。本例中的函数没有时间依赖性(它不使用 $.fadeIn 或类似的东西),所以我使用 $.delay 错开帧。

【讨论】:

$.queue 基本上是对存储在 $.data 中的数组的推送,这就是为什么您必须手动告诉它使用 cb() 执行下一个函数的原因;我的理解正确吗?【参考方案5】:

队列中的多个对象动画

这是一个队列中多个对象动画的简单示例。

Jquery 允许我们仅对一个对象进行排队。但是在动画函数中,我们可以访问其他对象。在此示例中,我们在 #q 对象上构建队列,同时为 #box1 和 #box2 对象设置动画。

将队列想象成一个函数数组。因此,您可以将队列作为数组进行操作。您可以使用 push、pop、unshift、shift 来操作队列。在本例中,我们从动画队列中移除最后一个函数并将其插入到开头。

完成后,我们通过 dequeue() 函数启动动画队列。

See at jsFiddle

html:

  <button id="show">Start Animation Queue</button>
  <p></p>
  <div id="box1"></div>
  <div id="box2"></div>
  <div id="q"></div>

js:

$(function()

 $('#q').queue('chain',function(next)  
      $("#box2").show("slow", next);
  );


  $('#q').queue('chain',function(next)  
      $('#box1').animate(
          left: 60, duration:1000, queue:false, complete: next
      )
  );    


  $('#q').queue('chain',function(next)  
      $("#box1").animate(top:'200',1500, next);
  );


  $('#q').queue('chain',function(next)  
      $("#box2").animate(top:'200',1500, next);
  );


  $('#q').queue('chain',function(next)  
      $("#box2").animate(left:'200',1500, next);
  );

  //notice that show effect comes last
  $('#q').queue('chain',function(next)  
      $("#box1").show("slow", next);
  );

);

$("#show").click(function () 
    $("p").text("Queue length is: " + $('#q').queue("chain").length);

    // remove the last function from the animation queue.
    var lastFunc = $('#q').queue("chain").pop();
    // insert it at the beginning:    
    $('#q').queue("chain").unshift(lastFunc);

    //start animation queue
    $('#q').dequeue('chain');
);

css:

        #box1  margin:3px; width:40px; height:40px;
                position:absolute; left:10px; top:60px; 
                background:green; display: none; 
        #box2  margin:3px; width:40px; height:40px;
                position:absolute; left:100px; top:60px; 
                background:red; display: none; 
        p  color:red;   

【讨论】:

以上是关于jQuery 中的队列是啥?的主要内容,如果未能解决你的问题,请参考以下文章

JQuery 中的 innerHTML 等价物是啥? [复制]

JavaScript/jQuery 中括号中的代码块是啥意思? [复制]

YUI 中的 jQuery outerHeight() 等价物是啥

jquery函数中的索引是啥意思

Javascript 或 jQuery 中的线程安全队列

$.noop() 在 jQuery 1.4 中的真正用途是啥?