2011-02-18 18 views
8

tengo página HTML muy simple con código JS:Javascript - asignar dinámicamente evento onclick en el bucle

<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> 

Esa página se une 10 botones, pero al hacer clic en cualquier botón que muestra siempre alerta "option9". ¿Cómo es posible asignar el evento onclick para mostrar la opción correspondiente?

Gracias!

Respuesta

28

Vas a tener que hacer algo como esto:

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

¿Qué está pasando realmente aquí? Esto funcionó para mí aswell, pero quiero entender aswell :-) – MartinElvar

+1

@MartinElvar creó una función que los argumentos son opt, a continuación, cuando aplicamos el (...) (arrOptions [i]) y luego se pasó a optar y luego cuando hacemos clic en btnShow, esta función se llama con los parámetros que se han establecido. – Yehonatan

+0

Una mejor manera, que no es tan confusa es usar el atributo "data" del nodo, y luego usar this.data como el parámetro de la función. Aquí hay un ejemplo: 'btnShow.data = arrOptions [i]; btnShow.onclick = function() { showParam (this.data); } ' –

2

considerar el hecho de que cuando se ejecuta la función onclick(), todo lo que tiene es:

showParam(optionPar); 

, palabra por palabra. La opción Par se resolverá en el momento en que se ejecute el evento de clic, y en este momento es muy probable que sea el último valor que le asignó. En general, debe evitar pasar variables de esa manera.

El problema que está tratando de resolver es el más resuelto por la re-escritura de la pieza, tales como:

  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

que adjuntar un controlador de eventos:

 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); 
      } 

que puede recuperar algo del elemento que activó el evento:

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

en cuyo caso debe incrustar la opción dentro del elemento/tag En mi caso, uso la identificación.

1

para jQuery, echa un vistazo a la adición de datos de eventos sección de la 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

se pasa simplemente la referencia de la variable a la función, no su valor. Por lo tanto, cada vez que se itera el ciclo, asigna una referencia a su función anónima y todos apuntan al mismo valor en la memoria. Pero dado que usa el mismo nombre de variable en el ciclo, sobrescribe el valor de la variable. Puede concatenar la variable a una cadena para preservar su valor. Por ejemplo, como que:

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

El primer parámetro es el nombre de la función, pero que yo sepa que es opcional (que puede dejarse en blanco o se omite en absoluto).

1

La respuesta aceptada parece funcionar, pero parece ser confusa y una forma algo engorrosa de hacerlo. Una mejor manera quizás sea utilizar el atributo de datos para el elemento que está buscando para asignar el detector de eventos. Es simple, fácil de entender y mucho menos código. Aquí hay un ejemplo:

btnShow.data = arrOptions[i]; 

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

La respuesta aceptada es correcta, pero creo que no se realizó ninguna explicación real.

Déjame intentar explicar, el problema aquí es el cierre clásico que falta.

La variable 'i' se está incrementado del 1 por repetición del bucle, y la sobre-evento Click en realidad no se está ejecutando, si sólo se aplica a la de un elemento, conseguir resumir hasta la longitud de arrOptions el cual es 10.

Así, el bucle continúa hasta 'i' es 10, Entonces, cada vez que el evento de clic está siendo disparado, se toma el valor de i que es 10.

ahora, para la solución, en la solución que estamos usando un cierre, de manera que cuando aplicamos el valor de 'i' a la víspera de clic nt del elemento a, en realidad obtiene el valor exacto de i en el tiempo.

la función interna del evento onclick crear un cierre donde se hace referencia al parámetro (arrOptions [i]), lo que significa que la variable i es real en el momento adecuado.

La función finalmente se cierra con ese valor de forma segura, y luego puede devolver su valor correspondiente cuando se está ejecutando el evento de clic.

Cuestiones relacionadas