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会使超时变量为空?
答案 0 :(得分:5)
您可以使用.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
,不同之处在于您进入孩子或孩子之间{{1} }不会再次触发,mouseenter
不会触发我们关心的父mouseleave
。
您可以使用上面的演示链接进行测试,我也将子项添加到第一个菜单,以证明它们是独立的。如果你碰巧对那里的$.proxy
有疑问,那就是在{10}内部使用<li>
匿名函数引用我想要的东西(当前this
)...元素在超时后需要关闭。
答案 1 :(得分:0)