Как предотвратить jQuery-код от слишком много функций вложенности?
Я не знаю, правильно ли вызывается это гнездование или нет? Но я знаю, что это не хороший код, чтобы иметь много функций внутри друг друга. Большинство методов jQuery имеют функцию обратного вызова, в которой мы можем поместить наши обратные вызовы. Но когда мы выполняем обратные вызовы внутри другого обратного вызова и продолжаем это и все глубже и глубже, кажется, что код становится менее читаемым и, возможно, менее отлаживаемым.
Например, если я хочу сделать несколько анимаций друг за другом, я должен вызывать каждую анимацию, которую я хочу получить после другой, в этой функции обратного вызова. Это будет глубже и глубже в функции обратного вызова. Посмотрите на этот пример (fiddle):
$('#t').animate({height: 400}, 500, function(){
$(this).animate({height: 200}, 500, function(){
$(this).animate({width: 300}, 500, function(){
$(this).animate({height: 300}, 500, function(){
$(this).animate({'border-radius': '50px'}, 500, function(){
//and so on...
});
});
});
});
});
для выполнения 5-ступенчатой анимации мне нужно сделать 5-уровневый стек вызовов. Итак, мой вопрос в том, как вы избегаете этого? У меня была такая же проблема и в моих Node.js-функциях.
Update:
Я знаю, что функция jQuery имеет функцию chinning, но это не решает проблему. потому что вы не можете сделать что-то среднее между цепочкой. Вы можете написать выше код типа $(selector').animate().animate()...
, но вы не можете сделать то же самое для этого:
$('#t').animate({height: 400}, 500, function(){
console.log('step 1 done: like a boss');
$(this).animate({height: 200}, 500, function(){
console.log('step 2 done: like a boss');
$(this).animate({width: 300}, 500, function(){
console.log('step 3 done: like a boss');
$(this).animate({height: 300}, 500, function(){
console.log('step 4 done: like a boss');
$(this).animate({'border-radius': '50px'}, 500, function(){
//and so on...
});
});
});
});
});
Идеальным решением будет такой код:
$(selector).doQ(anim1, anim2, myfunc1, anim3, myfunc2)...
Но, к сожалению, у jQuery нет такого API (насколько мне известно).
Ответы
Ответ 1
* "Идеальным решением будет такой код:
$(селектор).doQ(anim1, anim2, myfunc1, anim3, myfunc2)..." *
Это не совсем то, что вы хотите, но у jQuery есть queue()
[docs] метод:
$(selector).animate({height: 400}, 500)
.animate({height: 200}, 500)
.queue( myfunc1 )
.animate({width: 300}, 500)
.queue( myfunc2 );
Вам просто нужно убедиться, что ваши функции освободят очередь, когда они будут выполнены, используя dequeue()
[docs]:
function myfunc1() {
// your code
$(this).dequeue();
}
Или вы можете обернуть свои функции в анонимную функцию и вызвать там dequeue:
$(selector).animate({height: 400}, 500)
.animate({height: 200}, 500)
.queue( function( nxt ) {
myfunc1();
$(this).dequeue();
})
.animate({width: 300}, 500)
.queue( function( nxt ) {
myfunc2();
nxt(); // alternate way to dequeue
});
Ответ 2
Прочитайте очереди jQuery. Ваш код также может быть написан следующим образом:
$('#t')
.animate({height: 400}, 500)
.animate({height: 200}, 500)
.animate({width: 300}, 500)
.animate({height: 300}, 500)
.animate({'border-radius': '50px'}, 500);
Первая анимация запускается немедленно, а остальные помещаются в очередь "fx" и исполняются по очереди, когда остальные заканчиваются.
Ответ 3
Чтение на JQuery Отложенный объект
Это цельный объект утилиты, который может регистрировать несколько обратных вызовов в очереди обратного вызова, вызывать очереди обратного вызова и ретранслировать успех или состояние отказа любой синхронной или асинхронной функции.
Если ваши обратные вызовы являются ТОЛЬКО анимацией, тогда просто соедините их и используйте JQuery fx queue.
Ответ 4
Объекты jQuery имеют очередь по умолчанию. Попробуйте эту скрипту: http://jsfiddle.net/TbkjK/1/
Ответ 5
Немного более чистый способ:
$('#t')
.animate({height: 400}, 500, animationDone)
.animate({height: 200}, 500, animationDone)
.animate({width : 200}, 500, animationDone)
.animate({height: 300}, 500, animationDone)
.animate({'border-radius': '50px'}, 500, animationDone);
var logCount = 0;
function animationDone(e) {
logCount++;
$("#t").html("Animation # " + logCount + " has completed!");
}
Просто сделайте что-нибудь, основанное на числе logCount
. Пример можно увидеть здесь.
Ответ 6
что вы можете сделать, это определить функции с именем и ссылаться на них внутри другой функции, например
var clicka = function(){
alert("I got clicked after t.")
}
var clickt = function(){
alert("I got clicked!")
$('#a').click(clicka)
}
$('#t').click(clickt);