简单的jQuery下拉菜单 - clearTimeout,setTimeout问题

3

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);
} 

我遇到了超时问题。在使用中,如果我将鼠标悬停在“Three”上,下拉菜单会一直保持打开状态。如果我将鼠标悬停在“A”上,下拉菜单也会一直保持打开状态,但如果我将鼠标悬停在“B”或更低的位置,菜单就会关闭。如果您取消注释“// alert(timeout);”,它会针对B(和A)触发,但timeout将具有值。为什么会这样呢?我以为clearTimeout会将timeout变量设置为空值?

2个回答

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();
  });
});​

您可以在此处查看演示

与共享全局timeout变量不同,这将在每个顶级<li>中设置一个超时器,每个都有独立计时器,当您再次悬停在该元素上时,只会清除其计时器。此外,.hover()使用mouseentermouseleave,而不是mouseovermouseout,区别在于当您进入子级或在子级之间移动时,mouseenter不会再次触发,mouseleave不会在我们关心的父级<li>上触发。

您可以通过上面的演示链接进行测试,我还添加了第一个菜单的子项,以证明它们是独立的。如果您对其中的$.proxy有疑问,它只是使该超时匿名函数内的this指向我想要的内容(当前的this)...即在超时后需要关闭的元素。


0

你想要构建一个下拉菜单?为什么不使用现有的jQuery插件,或者更好的是,像http://purecssmenu.com/这样的纯CSS下拉菜单呢?


我正在尝试将其集成到现有的网站菜单中,因此我试图走最简单的路线。 - user210757

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接