¿Diferencia entre jQuery `click`,` bind`, `live`,` delegate`, `trigger` y` on` funciones (con un ejemplo)?

139

He leído la documentación de cada función jQuery official website, pero no hay tales listados de comparación entre las siguientes funciones:

$().click(fn)
$().bind('click',fn)
$().live('click',fn)
$().delegate(selector, 'click', fn)
$().trigger('click') // UPDATED
$().on('click', selector ,fn); // more UPDATED

Por favor, evite cualquier enlace de referencia.

¿Cómo funcionan exactamente todas las funciones anteriores y cuál debería preferirse en cada situación?

Nota: Si hay alguna otra función que tenga la misma funcionalidad o mecanismo, entonces explique.

Actualizar

También he visto una $.triggerfunción. ¿Funciona de manera similar a las funciones anteriores?

Más actualización

Ahora .onse agrega en v1.7 y creo que este de alguna manera cubre todos los requisitos de funciones anteriores juntos.

diEcho
fuente
3
@Me gusta PHP, a veces las personas votan en contra si no sienten que es una pregunta que no puede ser respondida por un manual o parece ser una pregunta de tarea. no se preocupe, otras personas lo votarán si lo encuentran útil.
typeoneerror
@ Typeoneerror - Gracias por el apoyo, ya leí el manual y cuando no entendí la clara diferencia, publiqué aquí.
diEcho
3
@ Me gusta PHP: edité la pregunta para un poco de limpieza ... esto a menudo se hace, pero rara vez de esta manera, puede ser fácilmente un valioso recurso apto para Google. Estoy de acuerdo en que una entrada wiki-ish de algo como esto sería muy útil, veo confusión al respecto, especialmente con .live()y .delegate()casi todos los días, +1 para una pregunta perfectamente válida.
Nick Craver
@Nick Craver Gracias por editar, en realidad soy malo en inglés (risas). ¿hay alguna referencia / referencia sobre cómo publicamos una pregunta SO? ot simplemente vino por experiencia
diEcho
@ Me gusta PHP: es un poco de ambos, hay una gran pregunta general para SO aquí: meta.stackexchange.com/questions/7931 Para la redacción / comentarios, simplemente comienza a aprender qué encaja y es la mejor manera de transmite tus pensamientos, codifica> cualquier descripción a veces, usando la palabra clave correcta, etiquetando apropiadamente, solo llega cuanto más tiempo estés aquí, supongo, veo muchos carteles mejorando con el tiempo. En cuanto a su edición, .trigger()solo invoca el controlador de eventos ... Agregaré una descripción a mi respuesta a continuación.
Nick Craver

Respuestas:

162

Antes de leer esto, suba esta lista de eventos en otra página, la API en sí es tremendamente útil, y todo lo que discuto a continuación está vinculado directamente desde esta página .

Primero, .click(function)es literalmente un atajo para .bind('click', function), son equivalentes. Úselos al vincular un controlador directamente a un elemento , así:

$(document).click(function() {
  alert("You clicked somewhere in the page, it bubbled to document");
});

Si este elemento es reemplazado o desechado, este controlador ya no estará allí. Además, los elementos que no estaban allí cuando se ejecutó este código para adjuntar el controlador (por ejemplo, el selector lo encontró entonces) no obtendrán el controlador.

.live()y .delegate()están relacionados de manera similar, en .delegate()realidad se usan .live()internamente, ambos escuchan eventos para burbujear. Esto funciona para elementos nuevos y antiguos , burbujean eventos de la misma manera. Los usa cuando sus elementos pueden cambiar, por ejemplo, agregando nuevas filas, elementos de la lista, etc. Si no tiene un padre / antecesor común que permanecerá en la página y no se reemplazará en ningún momento, use de .live()esta manera:

$(".clickAlert").live('click', function() {
  alert("A click happened");
});

Sin embargo, si tiene un elemento padre en algún lugar que no se está reemplazando (por lo que sus controladores de eventos no se están despidiendo), debe manejarlo de .delegate()esta manera:

$("#commonParent").delegate('.clickAlert', 'click', function() {
  alert("A click happened, it was captured at #commonParent and this alert ran");
});

Esto funciona casi igual que .live(), pero el evento burbujea menos veces antes de ser capturado y los controladores ejecutados. Otro uso común de ambos es decir que su clase cambia en un elemento, ya no coincide con el selector que utilizó originalmente ... con estos métodos, el selector se evalúa en el momento del evento , si coincide, el controlador se ejecuta. .so el elemento ya no coincide con el selector importa, ya no se ejecutará. Sin .click()embargo, el controlador de eventos está vinculado directamente al elemento DOM, el hecho de que no coincida con el selector utilizado para encontrarlo es irrelevante ... el evento está vinculado y permanece hasta que ese elemento desaparezca, o el controlador se elimina a través de .unbind().

Otro uso común para .live()y .delegate()es el rendimiento . Si se trata de muchos elementos, adjuntar un controlador de clic directamente a cada elemento es costoso y requiere mucho tiempo. En estos casos, es más económico configurar un solo controlador y dejar que el burbujeo haga el trabajo, eche un vistazo a esta pregunta donde marcó una gran diferencia , es un buen ejemplo de la aplicación.


Activación : para la pregunta actualizada

Hay 2 funciones principales de activación del controlador de eventos disponibles, se incluyen en la misma categoría de "Anexo de controlador de eventos" en la API , estas son .trigger()y .triggerHandler(). .trigger('eventName')tiene algunos atajos integrados para los eventos comunes, por ejemplo:

$().click(fn); //binds an event handler to the click event
$().click();   //fires all click event handlers for this element, in order bound

Puede ver una lista que incluye estos atajos aquí .

En cuanto a la diferencia, .trigger()activa el controlador de eventos (pero no la acción predeterminada la mayoría de las veces, por ejemplo, colocando el cursor en el lugar correcto en un clic <textarea>). Hace que los controladores de eventos se produzcan en el orden en que se vincularon (como lo haría el evento nativo), dispara las acciones de eventos nativos y burbujea el DOM.

.triggerHandler()generalmente tiene un propósito diferente, aquí solo está tratando de disparar los controladores vinculados, no causa que se active el evento nativo, por ejemplo, enviar un formulario. No burbujea el DOM, y no se puede encadenar (devuelve lo que devuelve el controlador de eventos de último enlace para ese evento). Por ejemplo, si desea desencadenar un focusevento pero no enfocar realmente el objeto, solo desea que se .focus(fn)ejecute el código que está vinculado , esto haría eso, mientras que.trigger() que haría eso y enfocaría el elemento y burbujearía.

Aquí hay un ejemplo del mundo real:

$("form").submit(); //actually calling `.trigger('submit');`

Esto ejecutaría cualquier controlador de envío, por ejemplo el complemento de validación jQuery , luego intentaría enviar el <form>. Sin embargo, si solo desea validar, ya que está conectado a través de un submitcontrolador de eventos, pero no envía el <form>posterior, puede usar .triggerHandler('submit'), de esta manera:

$("form").triggerHandler('submit');

El complemento evita que el controlador envíe el formulario bombardeando si la verificación de validación no pasa, pero con este método no nos importa lo que haga. Ya sea que haya sido cancelado o no, no estamos tratando de enviar el formulario, solo queríamos activarlo para volver a validarlo y no hacer nada más. ( Descargo de responsabilidad: este es un ejemplo superfluo ya que hay un .validate()método en el complemento, pero es una buena ilustración de la intención)

Nick Craver
fuente
Muy minucioso. Una pequeña corrección: triggerno dispara un evento nativo. Por nativo quiero decir un evento simulado con fireEvent(IE) o dispatchEvent(w3c).
Crescent Fresh
@Crescent: actualizado para que sea menos ambiguo, quise decir que activa las acciones nativas del evento , como el envío de formularios, el seguimiento de enlaces, etc. Espero que la actualización sea más clara :)
Nick Craver
@Nick de lo que estoy leyendo, parece que tu opinión live()es diferente de la que me diste aquí: stackoverflow.com/questions/3981762/… ¿El 'peso' sigue siendo una preocupación al usarlo live()?
Yahel
@yahelc - Sí, por supuesto ... esta respuesta está comparando estrictamente las opciones de los controladores de eventos y su propósito específico. El costo de peso frente al número de enlaces iniciales frente a si está agregando algo dinámicamente frente al selector inicial siguen siendo preocupaciones válidas. Si eres estructura de la página no es que grande que usted no tiene que muchos eventos entonces está bien ... la preocupación por el peso es directamente proporcional al tamaño / profundidad de su estructura y el número de eventos (de el tipo que .live()escucha su llamada, por ejemplo click) que se están generando, ya que ejecuta selectores para cada uno.
Nick Craver
1
en jQuery 1.7, live () está en desuso a favor de $ (document) .on ().
Synchro
28

Los dos primeros son equivalentes.

// The following two statements do the same thing:
$("blah").click( function() { alert( "Click!" ); } );
$("blah").bind( "click", function() { alert( "Click!" ); } ); 

Sin embargo, el segundo se puede usar para enlazar más de un evento al mismo tiempo, especificando varios nombres de eventos separados por espacios:

$("blah").bind( "click mouseover mouseout", function() { alert( "Click! Or maybe mouse moved." ); } ); 

El .livemétodo es más interesante. Considere el siguiente ejemplo:

<a class="myLink">A link!</a>
<a id="another">Another link!</a>

<script>
    $("a.myLink").click( function() { alert( 'Click!' ); } );

    $("a#another").addClass( "myLink" );
</script>

Después de que se ejecute la segunda línea del script, el segundo enlace también tendrá una clase CSS de "myLink". Pero no tendrá el controlador de eventos, porque no tenía la clase cuando se adjuntó el evento.

Ahora considere que desea que sea al revés: cada vez que aparece un enlace con la clase "myLink" en algún lugar de la página, desea que tenga el mismo controlador de eventos automáticamente. Esto es muy común cuando tiene algún tipo de listas o tablas, donde agrega filas o celdas dinámicamente, pero desea que todas se comporten de la misma manera. En lugar de pasar por todo el dolor de asignar controladores de eventos de nuevo cada vez, puede usar el .livemétodo:

<a class="myLink">A link!</a>
<a id="another">Another link!</a>

<script>
    $("a.myLink").live( "click", function() { alert( 'Click!' ); } );

    $("a#another").addClass( "myLink" );
</script>

En este ejemplo, el segundo enlace también obtendrá el controlador de eventos tan pronto como obtenga la clase "myLink". ¡Magia! :-)

Por supuesto, no es tan literal. Lo que .liverealmente hace es adjuntar el controlador no al elemento especificado en sí, sino a la raíz misma del árbol HTML (el elemento "cuerpo"). Los eventos en DHTML tienen esta característica divertida de "burbujear". Considera esto:

<div> <a> <b>text</b> </a> </div>

Si hace clic en "texto", primero el elemento <b> obtendrá un evento "clic". Después de eso, el elemento <a> obtendrá un evento "clic". Y después de eso, el elemento <div> obtendrá un evento "clic". Y así sucesivamente, hasta el elemento <body>. Y ahí es donde jQuery captará el evento y verá si hay controladores "en vivo" que se apliquen al elemento que causó el evento en primer lugar. ¡Ordenado!

Y finalmente, el .delegatemétodo. Simplemente toma todos los elementos secundarios de su elemento que se ajustan al selector dado y les adjunta un controlador "en vivo". Echar un vistazo:

$("table").delegate( "td", "click", function() { alert( "Click!" ); } );

// Is equivalent to:
$("table").each( function() {
    $(this).find( "td" ).live( "click", function() { alert( "Click!" ); } );
} );

Preguntas?

Fyodor Soikin
fuente
Para ser exactos, se .live()une a documentno <body>:) Puede ver una demostración aquí, simplemente levante la consola para inspeccionar: jsfiddle.net/aJy2B
Nick Craver
3
Era más conveniente explicarlo de esta manera. :-)
Fyodor Soikin
44
Lo suficientemente justo en la parte del "cuerpo", pero "todo el camino hasta el elemento <body>" está mal, los eventos continúan burbujeando allí, y no es donde .live()viven los manejadores, está por encima de eso, en document:) Puedes ver un demostración de esto aquí: jsfiddle.net/S2VBX
Nick Craver
8

A partir de jQuery 1.7, el método .live () quedó en desuso. Si está utilizando una versión jQuery <1.7, se recomienda oficialmente usar .delegate () sobre .live ().

.live () ahora ha sido reemplazado con .on ().

Es mejor ir directamente al sitio jQuery para obtener más información, pero aquí están las versiones actuales del método .on ():

.on( events [, selector] [, data], handler(eventObject) )
.on( events-map [, selector] [, data] )

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

Jonathan Tonge
fuente
2

$().click(fn)y $().bind('click', fn)son idénticos a primera vista, pero la $.bindversión es más poderosa por dos razones:

  1. $().bind()le permite asignar un controlador a múltiples eventos, por ejemplo $().bind('click keyup', fn),.
  2. $().bind()admite eventos con espacios de nombres: una característica poderosa si desea eliminar (desvincular) solo ciertos controladores de eventos a los que está vinculado un elemento; lea más en Eventos con espacios de nombres .

Live vs delegate: esto ya ha sido respondido en las otras respuestas.

fbuchinger
fuente
1

Aquí es donde la lectura de la API podría ayudar. Sin embargo, lo sé por lo alto de mi cabeza, por lo que puedes seguir siendo vago (¡yay!).

$('#something').click(fn);
$('#something').bind('click',fn);

No hay diferencia aquí (que yo sepa). .clickes simplemente un método de conveniencia / ayuda para.bind('click'

// even after this is called, all <a>s in
// <div class="dynamic_els"> will continue
// to be assigned these event handlers

$('div.dynamic_els a').live(‘click’,fn);

Esto es muy diferente, ya que .liveagrega eventos al selector que pasa (que no tiene aquí) y continúa mirando el DOM a medida que se insertan / eliminan los nodos

$('#some_element').delegate('td','click',fn);

Esto solo es diferente debido a la forma en que asigna los controladores de eventos. .delegatese centra en el evento DOM burbujeante. El principio básico es que cada evento burbujea hacia arriba a través del árbol DOM hasta que alcanza el elemento raíz ( documento windowo <html>o<body> , no recuerdo exactamente).

De cualquier manera, está vinculando un onclickcontrolador a todos los <td>s dentro $('#some_element')(debe especificar un selector, aunque podría decir $(document)). Cuando se hace clic en uno de sus elementos secundarios, el evento aparece<td> . Luego puede extraer el elemento fuente del evento (que jQuery hace por usted automáticamente).

Esto es útil cuando hay toneladas de elementos y solo tiene unos pocos (o un punto central) por los que pasarán estos eventos. Esto ahorra el esfuerzo del navegador y la memoria para consolidar estos controladores de eventos en menos objetos.

Dan Beam
fuente
1
.live() también funciona como burbujeo de eventos, de hecho .delegate()es un contenedor para .live(), solo agrega un contexto y se vincula a un elemento que no sea documentcapturar las burbujas. Creo que su comprensión de cómo funcionan los controladores burbujeantes está un poco fuera de lugar (este es el aspecto más comúnmente incomprendido de jQuery 1.4, creo). El controlador solo está en el elemento al que lo ha vinculado, por lo que, sea cual sea el elemento que haya llamado .delegate(), o documenten el caso de .live()que un evento aparezca allí, comprueba el objetivo para ver si coincide con el selector, y si es así se ejecuta.
Nick Craver