在多个导航元素上有效地使用addEventListener

时间:2015-11-17 15:02:09

标签: javascript

我目前正在使用一些javascript来侦听id为#drop-nav-trigger的导航元素上的mouseenter。这个想法是,如果他们没有悬停超过250毫秒,那么元素下拉菜单不会激活。如果用户只是将鼠标移到元素上以到达页面上的其他位置,我想阻止它显示。它很棒!

但是现在我想对同一导航菜单中的两个或更多元素做同样的事情(但不是所有元素)。我该如何处理?我是否只是为每个想要拥有此功能的导航项复制我的javascript?或者有没有办法将它们整合到一个代码片段中?

以下是我的HTML示例。在这个例子中,我想让javascript观看mouseenter的前两个顶级元素,但忽略第三个元素。我认为has-submenu将是我需要注意的。

<ul class="main-nav-wrapper">
    <li id="drop-nav-trigger" class="nav-item has-submenu">
        Browse Products
        <div class="submenu">
            <a href="#">Item 1</a>
            <a href="#">Item 2</a>
        </div>
    </li>
    <li class="nav-item has-submenu">
        Second Top Level Item
        <div class="submenu">
            <a href="#">Item 1</a>
            <a href="#">Item 2</a>
        </div>
    </li>
    <li class="nav-item">
        Third Top Level Item
    </li>
</ul>

这是我的javascript。我也在那里使用一些jQuery来将active类添加到导航项。一旦脚本将active添加到元素,我就使用CSS来显示隐藏的子菜单。

我认为我的问题是,与侦听ID不同,我的类在多个元素之间共享。因此,如果我倾听它,我将最终将active添加到我的所有匹配元素中。

var timeoutId = null;
var el = document.getElementById("drop-nav-trigger");

/* Activate menu after a delay. */
if(el) {
    el.addEventListener('mouseenter',function() { 
       timeoutId = window.setTimeout(function(){

            $("#drop-nav-trigger").addClass("active");

       }, 250);
     } );

    // Cancel your action if mouse moved out within 2 sec
    el.addEventListener('mouseleave',function() { 
        window.clearTimeout(timeoutId);
        $("#drop-nav-trigger").removeClass("active");
    });

}

1 个答案:

答案 0 :(得分:2)

您可以使用jQuery的hover功能,该功能接受两个回调 - 一个用于mouseenter,一个用于mouseleave。我们在所有.has-submenu项上使用此功能。您担心将.active添加到所有匹配的子项中 - 在回调函数中,jQuery将实际元素作为this传递,因此我们可以使用它来确保我们只将它添加到正确的元素:< / p>

$('.has-submenu').hover(function() {
    //mouseenter callback

    //keep separate reference to this so we can use it in the timeout function
    var li = this;

    $(li).data('timeoutId', setTimeout(function() {
        $(li).addClass('active');
    }, 250));

}, function() {
    //mouseleave callback
    clearTimeout($(this).data('timeoutId'));
    $(this).removeClass('active');
});

此外,我使用data函数将计时器ID存储在每个单独的元素上,这样它们就不会相互干扰,同时也消除了对{{{3}}的需求。 1}}变量超出了这些函数的范围。