将事件添加到新节点

时间:2012-01-16 05:37:55

标签: javascript addeventlistener

我一直在尝试使用for循环将click个事件添加到一系列divsdivs是动态创建和加载的。每个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。

3 个答案:

答案 0 :(得分:8)

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 :(得分:3)

这是因为你在事件处理程序中使用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 :(得分: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