【问题标题】:Add events to new nodes将事件添加到新节点
【发布时间】:2012-02-11 03:59:02
【问题描述】:

我一直在尝试使用 for 循环将 click 事件添加到一系列 divs 中。 divs 是动态创建和加载的。每个 div 都应该调用自己的回调函数。但是似乎每个div都附加到最终事件侦听器并调用最终事件侦听器的回调函数。

下面是我的基本代码:

for(index=0; index<divs.length; index++) {
  divs[index].addEventListener("click", function(){console.log(divs[index].getAttribute("id"));}, true); //capture click event
}

点击时,每个 div 只会显示最终 div 的 id。

【问题讨论】:

  • 阅读有关 javascript 闭包的信息,并编辑您的代码。这是一个变量范围问题。

标签: javascript addeventlistener


【解决方案1】:

这是因为您在事件处理程序中使用了divs[index],在循环完成后,它被设置为最后一个元素。

请改用this。此外,您可以使用一个事件处理程序而不是创建一堆相同的闭包,例如

function logId(e) {
    console.log(this.getAttribute("id"));
}

...在你的循环中...

divs[index].addEventListener("click", logId, false);

https://developer.mozilla.org/en/DOM/element.addEventListener#Memory_issues

【讨论】:

    【解决方案2】:

    您可以使用@phil 指出的this 关键字。

    但是,为了解释你的问题是什么,考虑一下这个闭包:

    for(index=0; index<divs.length; index++) {
      (function(index){
          divs[index].addEventListener("click", function(){
              console.log(divs[index].getAttribute("id"));
          }, true);
      })(index);
    }
    

    现在,每个函数都有自己的index 变量副本。在您的代码中,它们都共享相同的变量;所以最后,index 将等于divs.length -1,无论实际点击的是哪个div

    【讨论】:

    • 您的插图也可以,但我仍然不明白 (function(arg){ statements })(arg) 是什么,谢谢您的帮助
    【解决方案3】:

    Phil's answer 为您发布的特定代码提供了一个很好的解决方案 (+1),但没有解释您的原始代码存在什么问题。

    问题在于,事件处理程序闭包获得了对index 变量的持久引用,而不是创建时的副本。所以他们都看到了index 的最终值(divs.length)。比如这段代码

    for (index = 0; index < 4; ++index) {
        setTimeout(function() {
            console.log(index);
        }, 100);
    }
    

    ...发生超时时将记录四次“4”,而不是“0”、“1”、“2”和“3”。

    要在您希望确保处理程序关闭特定值的一般情况下更正它,请使用为您生成事件处理程序函数的工厂函数,其中事件处理程序关闭您提供给工厂函数的参数而不是循环变量:

    for(index=0; index<divs.length; index++) {
        divs[index].addEventListener("click", createHandler(divs[index], true); //capture click event
    }
    
    function createHandler(div) {
        return function(){
            console.log(div.getAttribute("id"));
        };
    }
    

    在那里,事件处理程序关闭 div,这不会改变。

    闭包是 JavaScript 最强大的功能之一。一旦您了解了它们的工作原理(并且它们实际上比人们想象的要简单得多),您就可以使用它们来产生非常好的效果。更多:Closures are not complicated

    【讨论】:

    • +1 用于描述大问题。您的 createHandler 方法也适用于 IE 的 (attachEvent 而我的则不行(this 支持已损坏)
    • @T.J. Crowder 闭包很有趣,谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-15
    相关资源
    最近更新 更多