将事件添加到新节点

Asu*_*sur 1 javascript addeventlistener

我一直在尝试使用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
}
Run Code Online (Sandbox Code Playgroud)

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

T.J*_*der 8

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

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

for (index = 0; index < 4; ++index) {
    setTimeout(function() {
        console.log(index);
    }, 100);
}
Run Code Online (Sandbox Code Playgroud)

...当超时发生时,将记录"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"));
    };
}
Run Code Online (Sandbox Code Playgroud)

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

闭包是JavaScript最强大的功能之一.一旦你理解它们是如何工作的(它们实际上比人们想象的要简单得多),你就可以使用它们来达到很好的效果.更多:关闭并不复杂