Controladores de eventos JQuery: ¿cuál es el “mejor” método

¿Cuál es la diferencia entre las siguientes formas de adjuntar un controlador de eventos en JQuery?

(function () { var $body = $("body"); $('button').click(function () { console.log(this) + " - 1"; }); $('button').on('click', function () { console.log(this) + " - 2"; }); $(document).on('click', 'button', function () { console.log(this) + " - 3"; }); $body.on('click', 'button', function () { console.log(this) + " - 4"; }); $body.find('button').on('click', function () { console.log(this) + " - 5"; }); })(); 

He encontrado algunos casos donde uno parece funcionar y el otro no. Por ejemplo Handler 2 a continuación, no funciona mientras Handler 1 lo hace. Para hacer que esto funcione, tuve que implementar Handler 3, que obviamente es menos eficiente.

 $retrieveCust = $("#bxRetrieveCustomer"); // Handler 1 $retrieveCust.find(".icoX").on("click", function () { // DO SOMETHING }); // Handler 2 $retrieveCust.find(".tag-open").on("click", function () { // DO SOMETHING }); // Handler 3 $(document).on("click", ".tag-open", function (event) { // DO SOMETHING }); 

Aquí está el HTML

 

RETREIVE CUSTOMER

X
First Name Last Name Date of Birth Email password

Supongo que está viendo una diferencia en el comportamiento debido a que algunos objetos en su página se agregan / eliminan dinámicamente y necesita un manejo de eventos delegado para tener automáticamente eventos para los objetos recién agregados.

Entre sus diversos ejemplos, hay dos tipos básicos de comportamientos aquí:

Comportamiento n. ° 1: enlace de eventos estáticos

 $('button').click(function () { console.log(this) + " - 1"; }); $('button').on('click', function () { console.log(this) + " - 2"; }); $body.find('button').on('click', function () { console.log(this) + " - 5"; }); 

Los tres anteriores adjuntan un manejador de clics directamente a cada objeto de botón que existe en la página en el momento en que se ejecuta el código por primera vez. Estos son básicamente idénticos. La syntax .click() es solo un acceso directo. $body.find('button') es funcionalmente equivalente a $('button') ya que ambos seleccionan todos los botones en el cuerpo.

Nota: estos controladores de eventos solo se adjuntarán a los objetos de botón que existen cuando este código se ejecuta por primera vez. Cualquier objeto de botón que se agregue posteriormente al documento no tendrá asociado un controlador de eventos.

Comportamiento n. ° 2: enlace de evento dynamic o delegado

 $(document).on('click', 'button', function () { console.log(this) + " - 3"; }); $(document.body).on('click', 'button', function () { console.log(this) + " - 4"; }); 

Estos dos usan el manejo de eventos delegates para ver si hay clics que burbujean en el documento u objetos del cuerpo. Estos son igualmente similares. Estos manejarán cualquier evento de clic que se origine en una etiqueta de botón. Dado que el controlador de eventos no está conectado directamente al objeto del botón, los botones pueden aparecer y desaparecer en la página y todos los objetos de botón que existen en cualquier momento obtendrán este comportamiento del controlador.

En general, NO se recomienda vincular los métodos delegates vinculados al document u objetos del body . De hecho, esta es la razón .live() cual .live() ha quedado obsoleto porque eso es lo que hizo y puede causar problemas de rendimiento. El problema es que si obtiene muchos eventos delegates, todos vinculados al mismo objeto, entonces cada vez que ocurre un evento y surge hasta este objeto, jQuery tiene que comparar el selector de origen con una gran cantidad de selectores diferentes para ver a qué manejador llamada.

Es mucho mejor vincular los eventos delegates a un objeto principal que esté lo más cerca posible de los objetos objective reales, pero obviamente debe elegir un objeto primario que no se agregará ni se eliminará (necesita uno que esté constantemente en la página). )

En su ejemplo de código más específico, suponiendo que el div bxRetrieveCustomer no se crea dinámicamente, debe cambiar esto:

 $(document).on("click", ".tag-open", function (event) { // DO SOMETHING }); 

a esto:

 $("#bxRetrieveCustomer").on("click", ".tag-open", function (event) { // DO SOMETHING }); 

Que seguirá delegado el manejo de eventos, pero vinculará el controlador de eventos mucho más cerca del objeto real para que funcione de manera más eficiente.

Eficiencia

En cuanto a cuál es el mejor, depende:

Si tiene objetos que se crean después de ejecutar el código de vinculación de eventos al que desea vincular los eventos, querrá usar el manejo delegado de eventos en el objeto ancestro más cercano que no se crea dinámicamente después de los hechos.

Si tiene una gran cantidad de objetos (incluso si son estáticos), el manejo de eventos delegates se instalará mucho más eficientemente porque instala un controlador de eventos para todos ellos en lugar de miles para cada objeto individual.

Si tiene un número medio o pequeño de objetos estáticos, entonces el enlace de los manejadores de eventos directamente a ellos es el más eficiente. Tomará un poco más de tiempo vincular inicialmente un controlador de eventos a cada objeto, pero luego será el más eficiente en el momento del evento.

si quieres, te recomiendo usar .on () porque puedes crear algún tipo de método genérico que también se pueda reutilizar para otros eventos pasando el argumento (es decir, el nombre del evento). Generalmente uso .on ()