2012-01-16 105 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