jQuery 怎样延迟触发鼠标经过(hover)的事件?

昨天设计了一番 V2MM 的板块列表,现在在电脑上鼠标移到左上角的板块图标上,会弹出一个 Dropdown 显示所有的板块, 而当鼠标移走的时候, Dropdown 会自动关闭。

怎样实现的?

Dropdown 使用的是 Bootstrap 的组件,HTML 代码如下:

<li class="dropdown">  
  <a href="/categories" title="" id="dropdown-categories" data-original-title="版块" class="dropdown-toggle">
     <i class="fa fa-fw fa-list"></i>
     <span class="visible-xs-inline">版块</span>
  </a>
  <div class="categories-tree dropdown-menu" aria-labelledby="dropdown-categories">
  </div>
</li>  

然后通过 js 监听 mouse-enter 事件则打开 dropdown, mouse-leave 则关闭。

$('#dropdown-categories').mouseenter(function () {
    $('#dropdown-categories').parent().addClass("open");
});
$('#dropdown-categories').parent().mouseleave(function () {
    $('#dropdown-categories').parent().removeClass("open");
});

但是这样做有个问题,那就是鼠标稍微移除 dropdown 就会关闭,太过于灵敏则很容易误操作,这种用户体验并不好。 怎么办呢? 网上的解决方案五花八门。

怎样延迟触发鼠标经过(hover)的事件?

  • 有一种解决方法是通过 setTimeout 并保存 timeoutId 记录来解决:
$("someelement").mouseenter(function(){
    clearTimeout($(this).data('timeoutId'));
    $(this).find(".tooltip").fadeIn("slow");
}).mouseleave(function(){
    var someElement = $(this),
        timeoutId = setTimeout(function(){
            someElement.find(".tooltip").fadeOut("slow");
        }, 650);
    //set the timeoutId, allowing us to clear this trigger if the mouse comes back over
    someElement.data('timeoutId', timeoutId); 
});
  • 还有一个叫 HoverIntent 的 jQuery 插件专门用于解决这个问题。
  • 但我发现最简洁的解决方式是通过 :hover 这个伪CSS选择器来判断鼠标是否在被选中的元素内,实现方式如下:
$('#dropdown-categories').parent().mouseleave(function () {
    setTimeout(function () {
        // check the mouse has leave the element for a moment.
        if(!$('#dropdown-categories').parent().is(":hover")) {
            $('#dropdown-categories').parent().removeClass("open");
        }
    }, 300);
});

如此简洁有效对吗? 但是 .is(":hover") 的这种判断方式竟然只有 jQuery 1.8 及以下版本才支持,于是最好的办法是通过 $('#dropdown-categories:hover').length 来判断。


参考: