2012-01-16 106 views
1

我一直试图使用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的ID。

+0

阅读关于JavaScript闭包,并编辑您的代码。这是一个可变范围问题。 – DhruvPathak 2012-01-16 05:40:10

回答

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

+0

+1 。你的'createHandler'方法也可以在IE的(<9)'attachEvent'中工作,而我的不会(这个'支持被破坏) – Phil 2012-01-16 06:02:04

+0

@ T.J。克罗德关闭很有趣,thanx – 2012-01-17 15:00:28

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

+0

+1使用'this'的好主意。 – 2012-01-16 05:43:58

+0

@Phil,thanx,这确实有帮助 – 2012-01-16 06:23:52

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实际上被点击。

+0

你的插图也适用,但我仍然不明白什么(函数(arg){语句})(arg),thanx对你的帮助 – 2012-01-17 15:03:31