Я обнаружил, что документ jQuery.com на queue()
/dequeue()
слишком прост для понимания. Что такое очереди в jQuery? Как их использовать?
Какие очереди в jQuery?
Ответ 1
Использование 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
выполняет следующую функцию и запускает ее, если очередь не запущена. - "inprogress":. Когда вы
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');
Очередь вызовов Ajax:
Я разработал плагин $.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, на этом сайте есть другие замечательные статьи о очередях, посмотрите.
Ответ 2
Чтобы понять метод очереди, вам нужно понять, как 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/
Сообщите мне, если у вас остались вопросы.
Ответ 3
Анимация нескольких объектов в очереди
Вот простой пример анимации нескольких объектов в очереди.
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; }
Ответ 4
Это позволяет вам помещать в очередь анимации... например, вместо этого
$('#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
Ответ 5
Этот поток очень помог мне с моей проблемой, но я использовал $.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.
Ответ 6
Функция 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>