Как предотвратить jQuery-код от слишком много функций вложенности?

17

Я не знаю, правильно ли вызывается этот nesting ? Но я знаю, что это не хороший код, чтобы иметь много функций внутри друг друга. Большинство методов jQuery имеют функцию обратного вызова, в которой мы можем поместить наши обратные вызовы. Но когда мы выполняем обратные вызовы внутри другого обратного вызова и продолжаем это и все глубже и глубже, кажется, что код становится менее читаемым и, возможно, менее отлаживаемым.

Например, если я хочу сделать некоторые анимации после друг друга, я должен вызывать каждую анимацию, которую я хочу получить после другой, в ее функции обратного вызова. Это будет глубже и глубже в функции обратного вызова. Посмотрите на этот пример ( скрипка ):

$('#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 (насколько мне известно).

    
задан Mohsen 18.09.2011 в 23:45
источник

6 ответов

23
  

* "Идеальным решением будет такой код:

     

$ (селектор) .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
            });
    
ответ дан user113716 19.09.2011 в 00:20
источник
7

Прочитайте очереди jQuery. Ваш код также может быть написан следующим образом:

$('#t')
    .animate({height: 400}, 500)
    .animate({height: 200}, 500)
    .animate({width: 300}, 500)
    .animate({height: 300}, 500)
    .animate({'border-radius': '50px'}, 500);

Первая анимация запускается немедленно, а остальные помещаются в очередь «fx» и исполняются по очереди, когда остальные заканчиваются.     

ответ дан Matt Bradley 18.09.2011 в 23:51
источник
4

Читайте в отложенном объекте JQuery

  

Это цельный объект утилиты, который может регистрировать несколько обратных вызовов   в очереди обратного вызова, вызывать очереди обратного вызова и ретранслировать успех или   состояние отказа любой синхронной или асинхронной функции.

Если ваши обратные вызовы являются ТОЛЬКО анимацией, тогда просто соедините их и используйте очередь fx JQuery.

    
ответ дан AlienWebguy 18.09.2011 в 23:51
источник
4

Объекты jQuery имеют очередь по умолчанию. Попробуйте эту скрипту: Ссылка

    
ответ дан gislikonrad 18.09.2011 в 23:52
источник
2

Немного более чистый способ:

$('#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 . Пример можно увидеть здесь .

    
ответ дан Shaz 19.09.2011 в 00:42
источник
0

что вы можете сделать, это определить функции с именем и ссылаться на них внутри другой функции, например

  var clicka = function(){
    alert("I got clicked after t.")
  }
  var clickt = function(){
        alert("I got clicked!")
        $('#a').click(clicka)
  }
  $('#t').click(clickt);
    
ответ дан bigblind 18.09.2011 в 23:50
источник