¿Cómo adjunto eventos a elementos HTML dinámicos con jQuery? [duplicar]

Resuelto frankadelic asked hace 15 años • 8 respuestas

Supongamos que tengo algún código jQuery que adjunta un controlador de eventos a todos los elementos con clase .myclass.

Por ejemplo:

$(function(){
    $(".myclass").click( function() {
        // do something
    });
});

Y mi HTML podría ser el siguiente:

<a class="myclass" href="#">test1</a>
<a class="myclass" href="#">test2</a>
<a class="myclass" href="#">test3</a>

Eso funciona sin problema. Sin embargo, considere si los .myclasselementos se escribieron en la página en algún momento futuro.

Por ejemplo:

<a id="anchor1" href="#">create link dynamically</a>
<script type="text/javascript">
$(function(){
    $("#anchor1").click( function() {
        $("#anchor1").append('<a class="myclass" href="#">test4</a>');
    });
});
</script>

En este caso, el test4enlace se crea cuando un usuario hace clic en a#anchor1.

El test4enlace no tiene el click()controlador asociado, aunque sí lo tiene class="myclass".

Básicamente, me gustaría escribir el click()controlador una vez y que se aplique tanto al contenido presente al cargar la página como al contenido incorporado más tarde a través de AJAX/DHTML . ¿Alguna idea de cómo puedo solucionar este problema?

frankadelic avatar Sep 01 '09 02:09 frankadelic
Aceptado

Estoy agregando una nueva respuesta para reflejar los cambios en versiones posteriores de jQuery. El método .live() está obsoleto a partir de jQuery 1.7.

Desde http://api.jquery.com/live/

A partir de jQuery 1.7, el método .live() está en desuso. Utilice .on() para adjuntar controladores de eventos. Los usuarios de versiones anteriores de jQuery deberían utilizar .delegate() en lugar de .live().

Para jQuery 1.7+, puede adjuntar un controlador de eventos a un elemento principal usando .on() y pasar un selector combinado con 'myclass' como argumento.

Ver http://api.jquery.com/on/

Entonces en lugar de...

$(".myclass").click( function() {
    // do something
});

Puedes escribir...

$('body').on('click', 'a.myclass', function() {
    // do something
});

Esto funcionará para todas las etiquetas con 'miclase' en el cuerpo, ya sea que ya estén presentes o que se agreguen dinámicamente más adelante.

La etiqueta del cuerpo se utiliza aquí ya que el ejemplo no tenía una etiqueta circundante estática más cercana, pero cualquier etiqueta principal que exista cuando se produce la llamada al método .on funcionará. Por ejemplo, una etiqueta ul para una lista a la que se agregarán elementos dinámicos se vería así:

$('ul').on('click', 'li', function() {
    alert( $(this).text() );
});

Mientras exista la etiqueta ul, esto funcionará (aún no es necesario que existan elementos li).

Sean avatar Feb 17 '2012 15:02 Sean

A veces, hacer esto (la respuesta más votada) no siempre es suficiente:

$('body').on('click', 'a.myclass', function() {
    // do something
});

Esto puede ser un problema debido al orden en que se activan los controladores de eventos. Si se encuentra haciendo esto, pero está causando problemas debido al orden en que se maneja... Siempre puede incluirlo en una función, que cuando se llama "actualiza" el oyente.

Por ejemplo:

function RefreshSomeEventListener() {
    // Remove handler from existing elements
    $("#wrapper .specific-selector").off(); 

    // Re-add event handler for all matching elements
    $("#wrapper .specific-selector").on("click", function() {
        // Handle event.
    }
}

Debido a que es una función, cada vez que configuro mi oyente de esta manera, normalmente lo invoco cuando el documento está listo:

$(document).ready(function() {
    // Other ready commands / code

    // Call our function to setup initial listening
    RefreshSomeEventListener();
});

Luego, cada vez que agregue algún elemento agregado dinámicamente, llame a ese método nuevamente:

function SomeMethodThatAddsElement() {
    // Some code / AJAX / whatever.. Adding element dynamically

    // Refresh our listener, so the new element is taken into account
    RefreshSomeEventListener();
}

¡Ojalá esto ayude!

Saludos,

Chandler Zwolle avatar Jul 15 '2014 20:07 Chandler Zwolle

Después de jQuery 1.7 los métodos preferidos son .on() y .off()

La respuesta de Sean muestra un ejemplo.

Ahora en desuso:

Utilice las funciones jQuery .live()y .die(). Disponible en jQuery 1.3.x

De los documentos:

Para mostrar el texto de cada párrafo en un cuadro de alerta cada vez que se hace clic en él:

$("p").live("click", function(){
  alert( $(this).text() );
});

Además, el complemento livequery hace esto y admite más eventos.

Matt Brunell avatar Aug 31 '2009 19:08 Matt Brunell

Si está agregando un montón de anclajes al DOM, busque la delegación de eventos.

He aquí un ejemplo sencillo:

$('#somecontainer').click(function(e) {   
  var $target = $(e.target);   
  if ($target.hasClass("myclass")) {
    // do something
  }
});
ScottE avatar Aug 31 '2009 19:08 ScottE

Puedes vincular un evento de un solo clic a una página para todos los elementos, sin importar si ya están en esa página o si llegarán en algún momento futuro, así:

$(document).bind('click', function (e) {
   var target = $(e.target);
   if (target.is('.myclass')) {
      e.preventDefault(); // if you want to cancel the event flow
      // do something
   } else if (target.is('.myotherclass')) {
      e.preventDefault();
      // do something else
   }
});

Lo he estado usando por un tiempo. Funciona de maravilla.

En jQuery 1.7 y posteriores, se recomienda usarlo .on()en lugar de vincular o cualquier otro método de delegación de eventos, pero .bind()aún funciona.

i-- avatar Mar 29 '2013 03:03 i--