Javascript 尽管有多个事件侦听器,函数只调用一次

Javascript function called only once despite multiple event listeners

我正在重建我自己的一个网站,专门为了 避免 使用 jQuery 因为我用得很少,所以不需要内存开销,并且我不关心是否支持旧版浏览器(我使用的 Firefox 版本可能是我访问过的网站中最旧的浏览器;因此,如果它们能正常工作,它们将适用于我 99.99% 的观众)。我在向文档中的几个列表项添加多个事件侦听器时遇到问题。

HTML 片段:

<div class="SubColumn LeftCol grid_12 alpha">
    <div class="InfoBox grid_12 alpha omega">
        <h1>Side Detail</h1>
        <ul>
            <li data-detail-item="Detail item" data-detail-info="Info about the detail item!">Detail item</li>
            <li data-detail-item="Detail item 2" data-detail-info="Info about the second detail item!">Detail item 2</li>
            <li>Detail item</li>
            <li>Detail item</li>
            <ul>
                <li>Detail item</li>
                <li>Detail item</li>
                <li>Detail item</li>
                <li>Detail item</li>
            </ul>
            <li>Detail item</li>
            <li>Detail item</li>
            <li>Detail item</li>
            <li>Detail item</li>
        </ul>
    </div>
</div>

相关Javascript:

function PrepareDefBoxes()
{
    // I'm using document.querySelectorAll() here as a generic swiss army knife
    // I use it multiple times throughout the script
    // Quite frankly its CSS-selector-syntax input is easier for me to read & maintain
    // CSS-style selectors even work on the custom data-* global attributes ^_^
    var AllDeets = document.querySelectorAll("li[data-detail-item][data-detail-info]");
    // An array of events to add to all the details list items
    // Declared here because I *might* need to add more events; you never know~
    var Events = ["mouseover", "mouseout", "click"];

    // This is a coding trick I've used in C++ and in php
    // If you have nested for loops and all your code is in the innermost loop,
    // you can actually put them all on the same line or on successive lines,
    // then have the scoping braces following the innermost for loop :3
    for(var i = 0; i < AllDeets.length; i++)
    for(var e = 0; e < Events.length; e++)
    {
        AllDeets[i].addEventListener( Events[e], function(event) {
            DefBox(event.target);
        });
        console.log("Added " + Events[e] + " to " + AllDeets[i].innerHTML);
    }
}

function DefBox(ListItem)
{
    console.log("It works!");
}

函数 PrepareDefBoxes() 由早期的 Bootstrap() 函数调用,该函数本身通过文档正文标记上的 onload 内联事件侦听器调用 <body onload="Bootstrap()">。当我刷新页面时,我将这段输出记录到控制台,完全符合预期:

Added mouseover to Detail item
Added mouseout to Detail item
Added click to Detail item
Added mouseover to Detail item 2
Added mouseout to Detail item 2
Added click to Detail item 2

但是,当我随机将鼠标悬停在应该有 THREE 个事件侦听器绑定到它们的两个列表项上时,函数 DefBox() 是只打过一次电话!并且它只会将其输出记录到控制台一次。我什至没有通过单击列表项获得额外的输出。当我将光标移到这两个项目上时,我应该会在控制台上打印出一堆乱七八糟的 "It works!"。

我谦虚地请求使用jQuery的解决方案,谢谢!

您的代码运行良好。我猜你只是误解了控制台输出信息。

参见fiddle:https://jsfiddle.net/3h4y0t01/1/(我只是让输出更明显):

var counter = 0;
function DefBox(ListItem)
{
    document.getElementById('out').innerHTML = counter++;
}