我想首先说我是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
答案 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;
});