Що таке черги в jQuery?


387

Я знайшов документ jQuery.com увімкнути queue()/ dequeue()занадто простий для розуміння. Які саме черги в jQuery? Як я повинен їх використовувати?


3
Хороший приклад вирішення проблеми з чергою: stackoverflow.com/questions/5230333 / ...
gnarf

Відповіді:


488

Використання jQuery .queue()та.dequeue()

Черги в jQuery використовуються для анімації. Ви можете використовувати їх з будь-якою метою. Вони являють собою масив функцій, що зберігаються на основі кожного елемента, використовуючи jQuery.data(). Вони "Перший-Перший-Вихід" (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. Черга за замовчуванням має деякі особливі властивості, які не поділяються з іншими чергами.

  1. Автозапуск: під час дзвінка$(elem).queue(function(){}); в fxчерзі буде автоматично dequeueнаступна функція і запустити його , якщо черга не почалася.
  2. Службова програма "inprogress": Коли ви dequeue()виконуватимете функцію з fxчерги, вона будеunshift() (натисне в перше місце масиву) рядок, "inprogress"який позначає, що в даний час виконується черга.
  3. Це за замовчуванням! 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черги з анімацією ( )

Запустити приклад на 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');

Черги на дзвінки в Аякс:

Я розробив $.ajaxQueue()плагін , який використовує $.Deferred, .queue()і $.ajax()також передати назад обіцянку , що НЕ буде вирішена , якщо запит НЕ завершиться. Ще одна версія, $.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 , на цьому сайті є інші чудові статті про черги, перегляньте.


+1. Я працюю над сценарієм користувача jQuery, який повинен підключитися до сценарію PHP так, ніби це інший скрипт PHP, що працює на клієнті - один запит HTTP / інша операція одночасно, тому це, безумовно, буде корисним. Лише питання: jQuery вимагає, щоб черги були приєднані до об'єктів, правда? Отже, який об’єкт я повинен використовувати? $(window)?
Будь ласка, продовжте

3
@idealmachine - Як видно з прикладу черги Ajax, ви можете фактично прикріпити події черги до порожнього об’єкта:$({})
gnarf

3
Цей підсумок неймовірно корисний. Щойно я закінчив створювати ледачий завантажувач для затримки запиту важкого вмісту, що знаходиться внизу екрана, доки він не прокручується до перегляду. Використання черги jQuery () зробило ці запити Ajax дуже гладкими (навіть якщо ви переходите прямо до нижньої частини сторінки). Дякую!
Джефф Стеден

14
Приємно дізнатись, чи ви все ще оновлюєте це для новіших версій jQuery. +1 :)
Шаз

3
Щоб додати одне для тих, хто просто вивчає черги та обіцянки тощо - у прикладі ajaxQueue, дзвінок на $ .ajaxQueue (), до якого ви поставите вам запит ajax, який ви хочете поставити в чергу (), поверне обіцянку. Те, як ви чекаєте, поки черга буде порожньою, це через promis.done (function () {alert ("done")}) ;. Знаходив мене на годину, щоб знайти це, тож сподіваюся, що це допоможе комусь іншому зберегти їх!
Росс

42

Щоб зрозуміти метод черги, ви повинні зрозуміти, як 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/

Повідомте мене, якщо у вас ще є питання.


20

Анімація декількох об'єктів у черзі

Ось простий приклад анімації декількох об’єктів у черзі.

Jquery дозволяє нам зробити чергу лише над одним об’єктом. Але в рамках функції анімації ми можемо отримати доступ до інших об'єктів. У цьому прикладі ми будуємо свою чергу над #q об'єктом, анімації об'єктів # box1 та # box2.

Подумайте про чергу як масив функцій. Таким чином, ви можете маніпулювати чергою як масивом. Ви можете використовувати натискання, попс, зсув, зміщення для керування чергою. У цьому прикладі ми видаляємо останню функцію з черги анімації та вставляємо її на початку.

Закінчивши, ми починаємо чергу анімації функцією dequeue ().

Дивіться на 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; }  

15

Це дозволяє встановлювати чергу з анімаціями ... наприклад, замість цього

$('#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 ставить їх у чергу, щоб виконувати їх по черзі. Використовуючи метод черги, тепер ви можете отримати доступ до цієї черги та маніпулювати нею, якщо це необхідно.
SolutionYogi

1
@SolutionYogi - Будь ласка, відредагуйте мою відповідь, якщо ви вважаєте, що вона неправильна - відповідь CW'd і у вас є достатня кількість представників.
alex

8

Цей потік мені дуже допоміг зі своєю проблемою, але я використовував $ .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');

Це спрощена версія сценарію, до якого я дійшов, але повинен показувати принцип - коли функція додається в чергу, вона додається за допомогою конструктора функцій - таким чином функцію можна динамічно записувати, використовуючи змінні з циклу ( з). Зауважте, як передається функція аргументу наступного () виклику, і це викликається в кінці. Функція в цьому випадку не залежить від часу (вона не використовує $ .fadeIn або щось подібне), тому я розміщую кадри за допомогою $ .delay.


$ .queue - це в основному поштовх до масиву, що зберігається у $ .data, через що вам потрібно вручну сказати йому, щоб виконати наступну функцію за допомогою cb (); Чи правильно моє розуміння?
вісімдесят

-1

Функціонування 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>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.