2012-01-06 22 views
190

Estoy usando jQuery v.1.7.1 donde aparentemente el método .live() está en desuso.jQuery .live() vs .on() método para agregar un evento de clic después de cargar html dinámico

El problema que estoy teniendo es que cuando se carga dinámicamente HTML en un elemento usando:

$('#parent').load("http://..."); 

Si trato y añadir un evento de clic después no se registra el evento utilizando cualquiera de estos métodos:

$('#parent').click(function() ...); 

o

// according to documentation this should be used instead of .live() 
$('#child').on('click', function() ...); 

Cuál es la forma correcta para lograr este fu nctionality? Parece que solo funciona con .live() para mí, pero no debería usar ese método. Tenga en cuenta que #child es un elemento cargado dinámicamente.

Gracias.

+24

¿Por qué dices * "supuestamente obsoleto" *? ¿No crees en los documentos? –

+6

No está, según parece, obsoleto: está _ desaconsejado. Si miras el [jQuery doco for '.live()'] (http://api.jquery.com/live/) te dice cómo reescribir los usos existentes de '.live()' para usar '.delegate() 'o' .on() '(dependiendo de si está en la versión 1.7+ o no). Sin embargo, tenga en cuenta que si agrega un controlador con '.click()' "después" como usted menciona, es decir, después de cargar elementos dinámicamente, debería funcionar; el único problema es tratar de asignar con '.click() '_antes de cargar dinámicamente elementos. – nnnnnn

+0

Cambié la fraseología a 'aparentemente' ya que eso es básicamente lo que quise decir. De todas formas, ahora entiendo que, dado que el evento .load() es asincrónico, el elemento #child solo podría reconocerse de manera confiable en el controlador de éxito, lo que tiene sentido. –

Respuesta

543

Si desea que el manejador de clics funcione para un elemento que se carga dinámicamente, configure el controlador de eventos en un objeto primario (que no se carga dinámicamente) y asígnele un selector que coincida con su objeto dinámico como este : manejador

$('#parent').on("click", "#child", function() {}); 

el evento se adjunta al objeto #parent y en cualquier momento un evento de clic burbujas hasta que que se originó en #child, se disparará el controlador de clic. Esto se denomina gestión delegada de eventos (el manejo de eventos se delega a un objeto principal).

Está hecho de esta manera porque se puede conectar el evento para el objeto #parent incluso cuando el objeto #child no existe todavía, pero cuando más tarde existe y se hace clic en, el evento click formarán burbujas al objeto #parent, se verá que se originó en #child y hay un controlador de eventos para un clic en #child y activa su evento.

+2

Buena explicación, gracias. –

+17

** ¡Excelente explicación! Nunca antes había sido capaz de entender 'live()' vs.' on() 'pero esta noche decidí intentarlo nuevamente, y tu explicación reveló inmediatamente lo que me había perdido todo el tiempo. ¡Gracias! – MikeSchinkel

+4

** Un millón de ups **. Empecé a utilizar el knockout antes de darme cuenta de que esto era posible en jQuery para niños dinámicamente creados, muchas gracias. –

20

$(document).on('click', '#selector', function() { /* do stuff */ });

EDIT: estoy proporcionando un poco más información sobre cómo funciona esto, porque ... palabras. Con este ejemplo, está colocando un oyente en todo el documento.

Cuando click en cualquier elemento (s) acorde con #selector, el evento se propaga hasta el documento principal - siempre y cuando no hay otros oyentes que llaman event.stopPropagation() método - que rematar el borboteo de un evento para elementos primarios .

En lugar de enlazar a un elemento específico o conjunto de elementos, está escuchando cualquier evento que provenga de elementos que coincidan con el selector especificado. Esto significa que puede crear un oyente, una vez, que coincidirá automáticamente con los elementos existentes actualmente, así como con cualquier elemento agregado dinámicamente.

Este es inteligente por varias razones, incluyendo el rendimiento y la utilización de la memoria (en aplicaciones a gran escala)

+0

Lo intentó .on() y dijo que no trabajando ... –

+22

Intentó '$ (elemento) .on (...)'. Esto es '$ (document) .on (..., element, ...)'. Diferentes bestias. – cHao

+0

Esto funcionó perfecto para mí, ¡gracias! –

4

.on() es para jQuery versión 1.7 o superior. Si tiene una versión anterior, utilice esto:

$("#SomeId").live("click",function(){ 
    //do stuff; 
}); 
+8

OP dice "Estoy usando jQuery v.1.7.1" –

+0

Todo lo que realmente puedo decirle es que no se admite debajo de eso. Tuve mala suerte con on() my self y revertí a live() en una aplicación empresarial que ejecutaba jQuery 1.7.1. –

+0

'.live()' ha quedado en desuso para todas las versiones de jQuery. Antes de 1.7, se recomienda usar '.delegate()', no '.live()'. – jfriend00

32

Prueba esto:

$('#parent').on('click', '#child', function() { 
    // Code 
}); 

Desde el $.on() documentación:

Los controladores de eventos sólo están vinculados a los elementos seleccionados en ese momento; ellos deben existir en la página en el momento en que su código realiza la llamada al .on().

Su elemento #child no existe cuando se llama a $.on() en él, por lo que el evento no está obligado (a diferencia de $.live()). #parent, sin embargo, existe, por lo que vincular el evento a eso está bien.

El segundo argumento en mi código anterior actúa como un 'filtro' para activar solo si el evento burbujeó hasta #parent desde #child.

+0

Si llamo al método $ .on() después del método $ .load(), ¿por qué no existiría el elemento #child en ese punto? –

+6

@SeanThoman - tendría que llamar desde el controlador de éxito del método '.load()' - no desde el código después del método '.load()'. '# child' solo se carga cuando el controlador de éxito se ejecuta realmente y no antes. – jfriend00

+0

e incluso entonces el tiempo que lleva insertar cualquier dato que haya ingresado al DOM significa que podría no conectarse. He estado haciendo un montón de trabajo de una sola página últimamente y mi estándar es var $ body = $ ('body'); $ body.on ("evento", ".element/# class", función (e) {}); para todo. 1 selector No se preocupe por lo que está o no cargado. – lupos

11

El equivalente de .live() en 1.7 se ve así:

$(document).on('click', '#child', function() ...); 

Básicamente, ver el documento para eventos de clic y filtrarlos para #child.

+1

¿Por qué $ (documento)? –

+0

Porque así es como el controlador de eventos se adjunta al documento (la forma en que '.live()' lo hace). – cHao

+16

Una razón por la que '.live()' está en desuso ahora es porque es malo poner todos los controladores de eventos en vivo en el objeto del documento. Las cosas realmente pueden ralentizarse. Los eventos no solo tienen que burbujear hasta el documento, sino que también puede tener muchos manejadores de eventos para examinar el objeto del documento. La principal ventaja de '.on()' es que puede adjuntarlo a un objeto principal que esté mucho más cerca del objeto real y mejorar drásticamente el rendimiento. Entonces ... NO recomendaría usar '.on()' con el objeto del documento. Mucho mejor para elegir un objeto primario más cercano. – jfriend00

3

Utilicé 'live' en mi proyecto, pero uno de mis amigos me sugirió que debería usar 'on' en lugar de live. Y cuando traté de usar, experimenté un problema como el que tenías.

En mis páginas creo filas de tablas de botones y muchas cosas dom dinámicamente. pero cuando lo uso en la magia desapareció.

Las otras soluciones como usarlo como un niño simplemente llama a sus funciones cada vez en cada clic. Pero encuentro la manera de hacerlo realidad nuevamente y aquí está la solución.

escribir el código como:

function caller(){ 
    $('.ObjectYouWntToCall').on("click", function() {...magic...}); 
} 

de llamadas de llamadas(); después de crear su objeto en la página de esta manera.

$('<dom class="ObjectYouWntToCall">bla... bla...<dom>').appendTo("#whereeveryouwant"); 
caller(); 

De esta manera se llama a su función cuando se supone que no cada clic en la página.

8

Sé que es un poco tarde para obtener una respuesta, pero he creado un polyfill para el método .live(). Lo probé en jQuery 1.11, y parece funcionar bastante bien. Sé que se supone que debemos implementar el método .on() siempre que sea posible, pero en proyectos grandes, donde no es posible convertir todas las llamadas .live() a las llamadas .on() equivalentes por el motivo que sea, el siguiente podría trabajo:

if(jQuery && !jQuery.fn.live) { 
    jQuery.fn.live = function(evt, func) { 
     $('body').on(evt, this.selector, func); 
    } 
} 

Solo tiene que incluirlo después de cargar jQuery y antes de llamar a live().