HTML:
<ul class="topnav">
<li><a href="#"><span>One</span></a></li>
<li><a href="#"><span>Two</span></a></li>
<li>
<li><a href="#"><span>Three</span></a></li>
<ul class="subnav">
<li><a href="#">A</a></li>
<li><a href="#">B</a></li>
<li><a href="#">C</a></li>
</ul>
</li>
</ul>
jquery:
var timeout = null;
$(document).ready(function() {
$("ul.topnav li").mouseover(function() {
if (timeout) clearTimeout(timeout);
$(this).find("ul.subnav").slideDown('fast').show();
}).mouseout(function() {
timeout = setTimeout(closemenu, 500);
});
// sub menu mouseovers keep dropdown open
$("ul.subnav li").mouseover(function() {
if (timeout) clearTimeout(timeout);
}
).mouseout(function() {
timeout = setTimeout(closemenu, 500);
// alert(timeout);
});
// any click closes
$(document).click(closemenu);
});
// Closes all open menus
function closemenu() {
$('ul.subnav:visible').hide();
if (timeout) clearTimeout(timeout);
}
我遇到超时问题。在使用中,如果我将鼠标悬停在“三”上,下拉菜单将永远保持不变。如果我将鼠标悬停在“A”上,下拉菜单将永远保留在外面,但如果我将鼠标悬停在“B”或更低的位置上,菜单将关闭。如果取消注释“//alert(timeout);” B(和 A)到达那里,但超时会有一个值。为什么是这样?我认为clearTimeout会使超时变量无效?
最佳答案
您可以使用 .hover()
整体简化代码和 .data()
像这样:
$(function() {
$("ul.topnav li").hover(function() {
var timeout = $(this).data("timeout");
if(timeout) clearTimeout(timeout);
$(this).find("ul.subnav").slideDown('fast');
}, function() {
$(this).data("timeout", setTimeout($.proxy(function() {
$(this).find("ul.subnav").slideUp();
}, this), 500));
});
$(document).click(function() {
$('ul.subnav:visible').hide();
});
});
You can see a working demo here
而不是共享全局 timeout
变量,这设置了每个顶级的超时 <li>
,每个元素都有一个独立的计时器,当您将鼠标悬停在该元素上时,只有其计时器被清除。另外 .hover()
使用 mouseenter
和 mouseleave
,而不是 mouseover
和 mouseout
,区别在于当你进入一个 child 或 child 之间时,mouseenter
不再触发,并且 mouseleave
不会向父级开火 <li>
我们关心。
您可以使用上面的演示链接对此进行测试,我还将子项添加到第一个菜单中,以证明它们是独立的。如果您碰巧对 $.proxy
有疑问在那里,它只是制作 this
在该超时匿名函数内引用我想要的内容(当前 this
)...超时后需要关闭的元素。
关于jquery - 简单的 jquery 下拉菜单 -clearTimeout、setTimeout 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2316213/