jQuery .when()。done()无效

我想首先说我是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

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

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

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

所以,在这一行:

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

ResetMenu()必须返回ResetMenu()一个promise来知道它何时完成。

您可以通过执行以下操作来修复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并将适当的值绑定到它:

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

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

当你将一个非promise对象传递给$.when() ,立即调用传递给done() $.when()的回调,在你没有返回任何东西的情况下立即调用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; });