2012-02-06 8 views
6

Мне показалось, что я понял силу цепочки jQuery, но теперь я немного смущен.простой jQuery Chaining insight

Используя пример выведения DIV, а затем удалить его:

  • По JQuery СЦЕПЛЕНИЯ логики, я должен быть в состоянии сделать:

    $(this).parent().fadeOut(500).remove(); 
    

Но вместо этого я необходимо сделать следующее:

$(this).parent().fadeOut(500,function() { $(this).remove(); }); 

Почему это? Благодаря!

ответ

11

Вы сразу же не можете позвонить .remove(), потому что операция .fadeOut() является асинхронной операцией, которая сразу возвращается (после того, как она только запускает анимацию), но продолжает выполнение через таймеры. Когда возвращается .fadeOut() и выполняется следующая цепочечная операция, анимация только что началась - она ​​еще не завершена. Если вы делаете .remove() с нормальной цепью, вы удаляете его прямо перед анимацией.

Итак, как вы выяснили, вам нужно подождать, пока на анимацию будет вызван обратный вызов завершения, а затем вы можете удалить его.

Единственное исключение - дополнительные прикованные анимационные вызовы. Вы можете связать анимацию, потому что анимация - это особый случай, который входит в очередь анимации. После начала анимации последующие вызовы анимации показывают, что уже идет анимация, и они входят во внутреннюю очередь. Когда первая анимация заканчивается, она проверяет очередь анимации, чтобы увидеть, есть ли больше анимации с цепочкой.

Почти все асинхронные операции в javascript не блокируются следующим образом. Это означает, что вызов их запуска - это просто призыв к их запуску. Затем этот вызов возвращается сразу, а оставшаяся часть операции выполняется через таймеры или другие события, а последующий javascript продолжает выполняться (включая другие цепные методы). Вы будете знать только, когда операция действительно выполняется путем регистрации для завершения обратного вызова завершения.

То же самое верно и для АЯКС операций, загрузка изображений, и т.д ...

Вы заставили меня задуматься о том, как сделать .remove() метод работы через очередь анимации. Можно на самом деле сделать это, создав новую версию удаления(), как это:

$.fn.fxRemove = function() { 
    this.queue(function(next) { 
     $(this).remove(); 
     next(); 
    }); 
    return(this); 
} 

Эта форма Вытащите идет в очереди анимации и будет выполняться при анимации прикован прежде, чем это делается. Таким образом, вы могли бы использовать:

$(this).parent().fadeOut(500).fxRemove(); 

Там есть рабочий пример здесь: http://jsfiddle.net/jfriend00/3Hg6G/

+1

Просто добавить к этому немного. Анимации добавляются в очередь, а не анимации. 'remove' - это не анимация, поэтому это происходит немедленно. Вставляя что-то вроде 'fadeIn' после того, как' fadeOut' будет ждать завершения 'fadeOut', потому что он попадает в очередь. Это часто неправильно понимают. –

+0

Мне сложно понять этот дизайн в jQuery. Разве это не обманывает большинство новичков (если не всех)? – Leo

+0

@ Leo - это не дизайнерское решение в jQuery. Из-за того, как работает javascript, операции, выполняемые в течение длительного периода времени с помощью браузера, способного реагировать на события, должны быть асинхронными (например, неблокирование). Когда они асинхронны, механизм javascript просто выполнит следующие операции с цепочкой. На самом деле нет другого способа использовать цепочку и решить эту проблему, если jQuery каким-то образом не поставит все связанные операции в очередь, и это может оказаться еще более сложным. Да, он обманывает новичков. Это то, что нужно изучать. – jfriend00

-1

Попробуйте это путь:

$(this).parent().fadeOut().delay(500).remove(); 
+0

Это тоже не сработает. '.delay()' не является синхронным. Он также асинхронный (проходит через очередь анимации) так же, как '.fadeOut()', поэтому он не будет задерживаться при вызове '.remove()'. – jfriend00

+0

Я думаю, вы обнаружите, что это совсем не помогает, потому что метод '.delay()' (http://api.jquery.com/delay/) только задерживает последующие методы анимации. – nnnnnn

0

Вы можете написать плагин, чтобы сделать его ждать.

DEMO

$.fn.q = function(fn) { 
    var that = this, arg = Array.prototype.slice.call(arguments, 1); 

    return this.queue(function(next) { 
     that[fn].apply(that, arg); 
     next(); 
    }); 
}; 

использование:

$(this).parent().fadeOut(500).q('remove');