【问题标题】:addEventListener in JS not working as expectedJS 中的 addEventListener 无法按预期工作
【发布时间】:2013-05-10 02:58:05
【问题描述】:

请先浏览代码。

index.html 是:

<html><head><title>Home</title><script src="js/script.js"></script></head>
<body onLoad="init()">

<ul class="sup" id="sup">

    <li class="supitem">
        <a href="#" class="supcont">Home<div class="v"></div></a>
        <ul class="sub">
            <li class="subitem"><a href="#" class="subcont">Home1</a></li>
            <li class="subitem"><a href="#" class="subcont">Home2</a></li>
            <li class="subitem"><a href="#" class="subcont">Home3</a></li>
        </ul>
    </li>

    <li class="supitem">
        <a href="#" class="supcont">Blog<div class="v"></div></a>
        <ul class="sub">
            <li class="subitem"><a href="#" class="subcont">Blog1</a></li>
            <li class="subitem"><a href="#" class="subcont">Blog2</a></li>
            <li class="subitem"><a href="#" class="subcont">Blog3</a></li>
        </ul>
    </li>

</ul>

</body>
</html>

script.js 是:

function init() {
    var sky = 0;
    var sup         = document.getElementById("sup");
    var supitems    = sup.getElementsByClassName("supitem");

    for (var i = 0, ln = supitems.length; i < ln; i++) {
        var supconts = supitems[i].getElementsByClassName("supcont");
        var subs = supitems[i].getElementsByClassName("sub");
        var supcont = supconts[0];

        supcont.innerHTML = "SuperMenu"+i;

        if (subs.length > 0) {
            var sub         = subs[0];

            supcont.addEventListener("click",function() {
                toggleVisibility(sub); });

            supcont.style.background = "#"+sky+sky+sky;
            sub.style.background = "#"+sky+sky+sky;
            sky += 4;
        }
    }
}

function toggleVisibility(object) {
    object.style.visibility =
        (object.style.visibility == "hidden" ?"visible" :"hidden");
}

我想做的是当我按下超级菜单时,所有子菜单的可见性都会被切换。但我不知道我在哪里犯了错误。当我按下 Supmenu0 时,会切换 Supmenu1 的子菜单,而不是 Supmenu1 的子菜单。提前致谢。

附:我认为问题出在 addEventListener。

【问题讨论】:

    标签: javascript html menu addeventlistener submenu


    【解决方案1】:

    这是一个常见问题,但我会尝试给出比我找到的更好的解释。当您将函数作为参数传递时(就像在定义事件处理程序时一样),javascript 不会评估该函数,而是将函数连同对其父级 scope 的引用一起存储。

    在触发事件处理程序之前,不会对函数进行评估。届时,解释器会检查父级scopesub 的值。因为这总是在你的for 循环完成后发生,所以它总是会找到sub 的最后一个值,即当你的for 循环完成时sub 是什么。所以你所有的事件监听器都会使用sub的最后一个值。

    我们可以通过创建closure 来获得所需的行为。替换这个:

    supcont.addEventListener("click",function() {
        toggleVisibility(sub); });
    

    用这个:

    (function(localSub) {
        supcont.addEventListener("click",function() {
            toggleVisibility(localSub);
        });    
    })(sub);
    

    之所以可行,是因为我们通过调用 IIFE 将每个事件处理程序声明与新的父 scope 包装在一起。这会强制事件处理程序在 IIFE 中保留 scope 的副本(称为在 scope 上创建闭包)。现在,当事件处理程序去寻找 localSub 时,它会在新的父 scope 中找到它,并且它将具有我们想要的值。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-08
    • 1970-01-01
    • 2013-12-23
    • 2014-12-09
    • 2016-01-13
    • 2020-09-21
    相关资源
    最近更新 更多