如何防止jQuery代码过多的嵌套函数?

时间:2011-09-18 21:45:36

标签: javascript 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函数也有同样的问题。

更新 我知道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(据我所知)。

6 个答案:

答案 0 :(得分:24)

  

*“理想的解决方案是这样的代码:

     

$(选择器).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();
}

或者你可以将你的函数包装在一个匿名函数中,然后调用然后在那里出列:

$(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
            });

答案 1 :(得分: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”队列中,当其他动画完成时依次执行。

答案 2 :(得分:4)

阅读JQuery的Deferred Object

  

它是一个可链接的实用程序对象,可以注册多个回调   进入回调队列,调用回调队列,并转发成功或   任何同步或异步函数的失败状态。

如果你的回调只是动画,那么只需链接它们并利用JQuery的fx队列。

答案 3 :(得分:4)

jQuery对象有一个默认队列。试试这个小提琴:http://jsfiddle.net/TbkjK/1/

答案 4 :(得分: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号码做一些事情。可以看到示例here

答案 5 :(得分:0)

您可以做的是使用名称定义函数,并在另一个函数中引用它们,例如

  var clicka = function(){
    alert("I got clicked after t.")
  }
  var clickt = function(){
        alert("I got clicked!")
        $('#a').click(clicka)
  }
  $('#t').click(clickt);