2011-02-18 71 views
8

我與JS代碼非常簡單的HTML頁面:使用Javascript - 動態分配onclick事件在循環

<html> 
    <head> 
     <title></title> 
    </head> 
    <body> 

     <div id="divButtons"> 

     </div> 

     <script type="text/javascript"> 
      var arrOptions = new Array(); 

      for (var i = 0; i < 10; i++) { 
       arrOptions[i] = "option" + i; 
      } 

      for (var i = 0; i < arrOptions.length; i++) { 
       var btnShow = document.createElement("input"); 
       btnShow.setAttribute("type", "button"); 
       btnShow.value = "Show Me Option"; 
       var optionPar = arrOptions[i]; 
       btnShow.onclick = function() { 
        showParam(optionPar); 
       } 

       document.getElementById('divButtons').appendChild(btnShow); 
      } 

      function showParam(value) { 
       alert(value); 
      }   
     </script> 
    </body> 
</html> 

該網頁結合10個按鈕,但是當你點擊任何按鈕,它總是顯示警報「選項9」。如何分配onclick事件來顯示相應的選項!

謝謝!

回答

28

你必須做這樣的事情:

btnShow.onclick = (function(opt) { 
    return function() { 
     showParam(opt); 
    }; 
})(arrOptions[i]); 
+4

這裏實際發生了什麼?這對我有用,但我也想明白:-) – MartinElvar 2012-08-08 16:56:34

2

考慮的是,被執行的onclick()函數時,所有它是:

showParam(optionPar); 

,一字不差。 optionPar將在點擊事件執行時解析,此時它最有可能是您分配給它的最新值。通常你應該避免以這種方式傳遞變量。

你正在試圖解決這個問題,最好通過重新編寫部分解決,如:

  btnShow.value = "Show Me Option"; 
      var optionPar = arrOptions[i]; 
      btnShow.optionPar = optionPar; 
      btnShow.onclick = function(e) { 
       // if I'm not mistaking on how to reference the source of the event. 
       // and if it would work in all the browsers. But that's the idea. 
       showParam(e.source.optionPar); 
      } 
1

我附加一個事件處理程序:

 window.onload = function() { 
      var folderElement; 
      tagFolders = document.getElementById("folders"); 
      for (i = 0; i < folders.length; i++) { 
       folderElement = folderButtons[i]; 
       folderElement = document.createElement("button"); 
       folderElement.setAttribute("id", folders[i]); 
       folderElement.setAttribute("type", "button"); 
       folderElement.innerHTML = folders[i]; 
       if (typeof window.addEventListener !== "undefined") { 
        folderElement.addEventListener("click", getFolderElement, false); 
       } else { 
        folderElement.attachEvent("onclick", getFolderElement); 
       } 
       tagFolders.appendChild(folderElement); 
      } 

可檢索的元素什麼那觸發了事件:

// This function is the event handler for the folder buttons. 
function getFolderElement(event) { 
    var eventElement = event.currentTarget; 
    updateFolderContent(eventElement.id); 
} 

在這種情況下,您必須將選項嵌入元素/標籤。在我的情況下,我使用ID。

1

jQuery的,請從API添加事件數據部分:

... 
for (var i = 0; i < arrOptions.length; i++) { 

    $('<input id="btn" type="button" value="Show Me Option"><input>').appendTo("#divButtons") 

    $('#btn').bind("click", { 
     iCount: i}, 
    function(event) { 
     showParam(arrOptions[iCount]); 
    }); 
} 
0

您傳遞變量的只是參考的功能,而不是它的價值。所以每次迭代循環時,它都會爲您的匿名函數分配一個引用,並且它們都指向內存中的相同值。但是由於您在循環中使用了相同的變量名稱,因此您會覆蓋該變量的值。您可以將該變量連接到一個字符串以保留其值。例如像:

btnShow.onclick = new Function("", "showParam(" + arrOptions[i] + ");"); 

第一個參數是所述函數的名稱,但它AFAIK是可選的(可以留爲空白或省略的話)。

1

接受的答案似乎工作,但似乎是混亂和一個有點麻煩的方式來做到這一點。一種更好的方法可能是使用data屬性來指定要指定事件偵聽器的元素。它很簡單,易於理解,而且代碼少。這裏有一個例子:

btnShow.data = arrOptions[i]; 

btnShow.onclick = function() { 
    showParam(this.data); 
} 
1

接受的答案是正確的,但我覺得沒有真正的解釋。

讓我試着解釋一下,這裏的問題是經典的缺失閉包。

變量「i」是越來越增加1每循環迭代, 和上點擊事件實際上沒有被執行,是否只施加到一個元件,它得到總結到arrOptions的長度這是10

所以,繼續循環,直到「i」是10, 然後,每當上點擊被觸發的事件,它需要我的值是10。

現在,對於解決方案,我們在解決方案中使用了一個閉包,所以當我們將'i'的值應用於點擊前夕時,解決方案中的 nt的元素,它實際上得到了我在時間上的確切值。

onclick事件的內部函數創建一個閉包,它引用參數(arrOptions [i]),這意味着實際的i變量在正確的時間。

該函數最終以該值安全關閉, ,然後可以在執行點擊事件時返回其相應的值。