jQuery .when()。done()无效

时间:2015-02-18 03:33:59

标签: jquery deferred

我想首先说我是jQuery的新手,我怀疑我只是在做一些愚蠢的事情,所以希望这对某些人来说非常简单。

我试图在我的网站上添加滑动移动子菜单。我想要一个手风琴效果,如果我点击一个父链接,它的子子菜单打开,所有其他子菜单关闭。问题是时间 - 子子菜单打开然后通过重置所有子菜单再次关闭。我认为答案是使用延迟,但我尝试过的一切都失败了。这是(当前不起作用)代码:

function ResetMenu(){
    jQuery(".mobile-menu").find(".sub-menu").slideUp(100);
    jQuery(".mobile-menu").find(".menu-item-has-child").removeClass("open");
};

function OpenSubmenu(){
    jQuery(this).next("ul").slideDown(100);
    jQuery(this).parent().addClass("open");
};

jQuery("li.menu-item-has-children > a").click(function(){

    if(jQuery(this).parent().hasClass("open")){
        jQuery(".mobile-menu").find(".sub-menu").slideUp(100);
        jQuery(this).parent().removeClass("open");
    } else {
        jQuery.when(ResetMenu()).done(OpenSubmenu());
    }
    return false;
});

非常感谢任何帮助。谢谢!

Ronel

2 个答案:

答案 0 :(得分:25)

这是如何使用jQuery.when()的常见错误。

jQuery.when()需要承诺作为参数。它没有神奇的力量来知道你传递它的功能何时以某种方式完成。这些函数必须返回在底层代码完成时被解析或拒绝的promise,然后你可以将这些promise传递给jQuery.when()

您的ResetMenu()函数无法返回任何内容,因此jQuery.when()不会等待任何事情。它立即执行.then()处理程序(看起来这不是你想要的)。

所以,在这一行:

jQuery.when(ResetMenu()).done(OpenSubmenu());

ResetMenu()必须返回jQuery.when()的承诺,知道它何时完成。

您可以通过以下方式修复ResetMenu()

function ResetMenu(){
    return jQuery(".mobile-menu").find(".sub-menu").slideUp(100).promise().then(function() {
        // remove this class when the animation has completed
        jQuery(".mobile-menu").find(".menu-item-has-child").removeClass("open");
    });
};

然后,您需要更改将函数传递给.done()的方式,这使得它只是一个函数引用,可以执行LATER并将适当的this值绑定到它:

jQuery.when(ResetMenu()).done(OpenSubmenu.bind(this));

注意,.bind(this)假定this是适当的值。您可以传递任何正确值的值,并且在执行时将成为this内的OpenSubmenu()值。

答案 1 :(得分:3)

当您将非承诺对象传递给$.when()时,会立即调用传递给done()的回调,如果ResetMenu未返回任何内容,则会调用OpenSubmenu立即,还有另一个问题 - 您不应该直接调用OpenSubmenu(通过添加()),您需要将函数引用传递给done()

function ResetMenu() {
    jQuery(".mobile-menu").find(".menu-item-has-child").removeClass("open");
    return jQuery(".mobile-menu").find(".sub-menu").slideUp(100).promise();

};

function OpenSubmenu() {
    jQuery(this).next("ul").slideDown(100);
    jQuery(this).parent().addClass("open");
};

jQuery("li.menu-item-has-children > a").click(function () {

    if (jQuery(this).parent().hasClass("open")) {
        jQuery(".mobile-menu").find(".sub-menu").slideUp(100);
        jQuery(this).parent().removeClass("open");
    } else {
        jQuery.when(ResetMenu()).done(OpenSubmenu);
    }
    return false;
});