设置超时/清除超时问题,似乎无法重置



我正在尝试创建悬停在菜单名称上时会下拉的菜单。由于名称和菜单div不相邻,我需要一种方法来延迟菜单的消失,这样用户就可以从名称移动到菜单本身。我为此使用了setTimeout。在菜单上悬停后,我需要它保持打开状态,直到鼠标离开,然后它应该隐藏起来。

我所尝试的完全是一团糟。不知道如何修复它。因为setTimeout在初始mouseover内部,所以计时器会自行循环。。。但如果我把setTimeout放在其他地方,它似乎就不起作用了。

这是代码:

$(document).ready(function() {
$('.headermenushow').mouseover(function () {
$(this).next('.dropmenu').show(0, function () {
timer = setTimeout(function() {
$('.dropmenu').hide(10);
}, 2000);
});
$(this).next('.dropmenu').mouseover(function () {
clearTimeout(timer);
});
});
});

下面是一个节略的jsfiddle,展示了我想如何使用它:

http://jsfiddle.net/H247x/1/

任何帮助都会很棒。不太确定如何让它更好地工作。。。

这个代码有各种各样的问题:

  1. 您正在.mouseover()事件中添加事件处理程序。这意味着,每次出现mouseover事件时,都会添加另一组事件处理程序。当ALL执行时,这些会堆积起来,造成真正的混乱。对于每个活动对象,您只需要一组事件处理程序。

  2. 你关于这应该如何运作的整个逻辑似乎有缺陷。只要鼠标位于某个项目上,您就希望菜单保持下拉状态。鼠标悬停事件仅在鼠标第一次移动到项目上时发生。当鼠标悬停在菜单上时,你没有任何方法可以关闭菜单,因为无论鼠标是否还在,你似乎只是在显示2秒后盲目地隐藏它。

  3. 您正在为计时器使用一个隐式全局变量。这就产生了一堆问题。首先,如果有多个.headermenushow对象,则每个对象的timer将踩在其他对象上。第二个隐式全局变量很糟糕,很容易导致错误。在您想要的范围内明确声明它。

  4. 你可以在计时器上计时。任何时候将计时器保存到共享变量中,都必须检查已运行的前一个计时器,或者在覆盖其变量之前停止任何前一个定时器。这可以防止丢失对正在运行的计时器的跟踪,并防止将多个计时器堆叠在一起,所有计时器都试图做相同的事情。

我们可能会帮助您想出更好的代码,但我们需要查看您的实际HTML,并更好地了解您试图实现的行为。

仅供参考,您可能还想查看CSS:hover选择器,它将允许您在悬停时显示/隐藏内容,而不需要任何JS代码。由于我不知道你的HTML是什么样子的,我不能确定这是否适用于你,但它被许多菜单系统使用。如果做得好,它真的很简单。


现在您已经展示了HTML,下面是一个有效的版本。我必须说,很多javascript是因为你的HTML并没有让它变得那么容易

$(document).ready(function() {
$(".headermenushow").hover(function() {
// hide any previous dropdown menus
$(".dropmenu").hide();
var self = $(this);
var timer = self.data("timer");
// show the dropdown menu for this item
self.next().show();
// clear any previous timer for this menu
if (timer) {
clearTimeout(timer);
self.data("timer", null);
}
}, function() {
// hide only on a delay so that user can move
// to the menu
var self = $(this);
var menu = self.next();
var timer = self.data("timer");
// clear any previous timer that might have been active
if (timer) clearTimeout(timer);
timer = setTimeout(function() {
self.data("timer", null);
// if mouse is not over the menu, then hide it
if (!menu.data("hover")) {
menu.hide();
}
}, 500);
self.data("timer", timer);
});
// keep track of hover state on the menu
$(".dropmenu").hover(function() {
$(this).data("hover", true);
}, function() {
$(this).data("hover", false);
$(this).hide();
});
});

工作演示:http://jsfiddle.net/jfriend00/YJu6Q/

最新更新