Я обнаружил, что документ jQuery.com на queue()
/dequeue()
слишком прост для понимания. Что такое очереди в jQuery? Как их использовать?
.queue()
и .dequeue()
Очереди в jQuery используются для анимации. Вы можете использовать их для любых целей. Они представляют собой массив функций, хранящихся на основе каждого элемента, используя jQuery.data()
. Это First-In-First-Out (FIFO). Вы можете добавить функцию в очередь, вызывая .queue()
, и вы удаляете (вызывая) функции с помощью .dequeue()
.
Чтобы понять внутренние функции очереди jQuery, чтение источника и просмотр примеров помогает мне чрезвычайно. Один из лучших примеров функции очереди, который я видел, - .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
выполняет следующую функцию и запускает ее, если очередь не запущена.dequeue()
выполняете функцию из очереди fx
, она будет unshift()
(нажмите в первую ячейку массива) строку "inprogress"
- который указывает, что очередь выполняется в настоящий момент.fx
используется .animate()
и всеми функциями, вызывающими ее по умолчанию. ПРИМЕЧАНИЕ. Если вы используете пользовательскую очередь, вы должны вручную .dequeue()
выполнять функции, они не будут запускаться автоматически!
Вы можете получить ссылку на очередь jQuery, вызвав .queue()
без аргумента функции. Вы можете использовать этот метод, если хотите посмотреть, сколько элементов находится в очереди. Вы можете использовать push
, pop
, unshift
, shift
для управления очередью на месте. Вы можете заменить всю очередь, передав массив функции .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
):$(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 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);
});
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');
Я разработал плагин $.ajaxQueue()
, который использует $.Deferred
, .queue()
и $.ajax()
, чтобы снова передать promise, который разрешен, когда запрос завершен. Другая версия $.ajaxQueue
, которая по-прежнему работает в версии 1.4, размещена в моем ответе на Последовательные запросы Ajax
/*
* 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, на этом сайте есть другие замечательные статьи о очередях, посмотрите.
$(window)
?
$({})
Чтобы понять метод очереди, вам нужно понять, как jQuery делает анимацию. Если вы пишете несколько вызовов метода animate один за другим, 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);
}
Теперь вы можете спросить, почему я должен беспокоиться об этой очереди? Обычно ты не хочешь. Но если у вас сложная последовательность анимации, которую вы хотите контролировать, методы queue/dequeue - ваш друг.
Также см. интересную беседу о группе jQuery о создании сложной последовательности анимации.
Демонстрация анимации:
http://www.exfer.net/test/jquery/tabslide/
Сообщите мне, если у вас остались вопросы.
Вот простой пример анимации нескольких объектов в очереди.
Jquery нам нужно сделать очередь только на одном объекте. Но внутри функции анимации мы можем получить доступ к другим объектам. В этом примере мы создаем нашу очередь над объектом #q во время анимации объектов # box1 и # box2.
Думайте о очереди как о множестве функций. Таким образом, вы можете манипулировать очередью как массив. Вы можете использовать push, pop, unshift, shift для управления очередью. В этом примере мы удаляем последнюю функцию из очереди анимации и вставляем ее в начале.
Когда мы закончили, мы запустим очередь анимации с помощью функции dequeue().
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; }
Это позволяет вам помещать в очередь анимации... например, вместо этого
$('#my-element').animate( { opacity: 0.2, width: '100px' }, 2000);
Затухает элемент и одновременно делает ширину 100 px . Использование очереди позволяет вам создавать анимации. Итак, один заканчивается после другого.
$("#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
Этот поток очень помог мне с моей проблемой, но я использовал $.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');
Это упрощенная версия script, к которой я пришел, но должен показать принцип - когда функция добавляется в очередь, она добавляется с помощью конструктора Function - таким образом, функция может быть записана динамически, используя переменные из цикла (ов). Обратите внимание, как функция передается аргументом для вызова next(), и это вызывается в конце. Функция в этом случае не имеет зависимости от времени (она не использует $.fadeIn или что-то в этом роде), поэтому я разбиваю кадры с помощью $.delay.
Функция makeRed
и makeBlack
использует queue
и dequeue
для выполнения друг друга. Эффект заключается в том, что элемент "#wow" постоянно мигает.
<html>
<head>
<script src="http://code.jquery.com/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>