De donde viene esto
Cuando aprendí jQuery por primera vez, normalmente adjunto eventos como este:
$('.my-widget a').click(function() {
$(this).toggleClass('active');
});
Después de aprender más sobre la velocidad del selector y la delegación de eventos, leí en varios lugares que "la delegación de eventos jQuery hará que su código sea más rápido". Entonces comencé a escribir código como este:
$('.my-widget').on('click','a',function() {
$(this).toggleClass('active');
});
Esta también fue la forma recomendada para replicar el comportamiento del evento .live () en desuso. Lo cual es importante para mí ya que muchos de mis sitios agregan / eliminan dinámicamente widgets todo el tiempo. Sin embargo, lo anterior no se comporta exactamente como .live (), ya que solo los elementos agregados al contenedor ya existente '.my-widget' obtendrán el comportamiento. Si agrego dinámicamente otro bloque de html después de que se haya ejecutado ese código, esos elementos no tendrán los eventos vinculados a ellos. Me gusta esto:
setTimeout(function() {
$('body').append('<div class="my-widget"><a>Click does nothing</a></div>');
}, 1000);
Lo que quiero lograr:
- El antiguo comportamiento de .live () // significa asociar eventos a elementos aún no existentes
- los beneficios de .on ()
- rendimiento más rápido para vincular eventos
- Manera simple de gestionar eventos
Ahora adjunto todos los eventos como este:
$(document).on('click.my-widget-namespace', '.my-widget a', function() {
$(this).toggleClass('active');
});
Lo que parece cumplir con todos mis objetivos. (Sí, es más lento en IE por alguna razón, ¿no se sabe por qué?) Es rápido porque solo un evento está vinculado a un elemento singular y el selector secundario solo se evalúa cuando se produce el evento (corríjame si esto está mal aquí). El espacio de nombres es increíble, ya que hace que sea más fácil alternar el escucha del evento.
Mi solución / pregunta
Así que estoy empezando a pensar que los eventos jQuery siempre deberían estar vinculados a $ (documento).
¿Hay alguna razón por la que no quieras hacer esto?
¿Podría considerarse esto una mejor práctica? Si no, ¿por qué?
Si has leído todo esto, gracias. Agradezco cualquier / todos los comentarios / ideas.
Suposiciones
- Usando jQuery que admite
.on()
// al menos la versión 1.7 - Desea que el evento se agregue al contenido agregado dinámicamente
Lecturas / ejemplos:
Respuestas:
No, NO debe vincular todos los controladores de eventos delegados al
document
objeto. Ese es probablemente el peor escenario que podría crear.En primer lugar, la delegación de eventos no siempre acelera su código. En algunos casos, es ventajoso y en otros casos no. Debe usar la delegación de eventos cuando realmente necesite delegación de eventos y cuando se beneficie de ella. De lo contrario, debe vincular los controladores de eventos directamente a los objetos donde ocurre el evento, ya que esto generalmente será más eficiente.
En segundo lugar, NO debe vincular todos los eventos delegados a nivel de documento. Esto es exactamente por qué
.live()
fue desaprobado porque esto es muy ineficiente cuando tienes muchos eventos vinculados de esta manera. Para el manejo de eventos delegados, es MUCHO más eficiente vincularlos al elemento primario más cercano que no sea dinámico.Tercero, no todos los eventos funcionan o todos los problemas pueden resolverse con delegación. Por ejemplo, si desea interceptar eventos clave en un control de entrada y bloquear que no se ingresen claves no válidas en el control de entrada, no puede hacerlo con el manejo de eventos delegados porque para cuando el evento llegue al controlador delegado, ya ha procesado por el control de entrada y es demasiado tarde para influir en ese comportamiento.
Aquí hay momentos en que la delegación de eventos es obligatoria o ventajosa:
Para entender esto un poco más, uno necesita entender cómo funcionan los controladores de eventos delegados de jQuery. Cuando llamas a algo como esto:
Instala un controlador de eventos genérico jQuery en el
#myParent
objeto. Cuando un evento de clic aparece en este controlador de eventos delegado, jQuery tiene que revisar la lista de controladores de eventos delegados adjuntos a este objeto y ver si el elemento de origen del evento coincide con alguno de los selectores en los controladores de eventos delegados.Debido a que los selectores pueden estar bastante involucrados, esto significa que jQuery tiene que analizar cada selector y luego compararlo con las características del objetivo del evento original para ver si coincide con cada selector. Esta no es una operación barata. No es gran cosa si solo hay uno de ellos, pero si pones todos tus selectores en el objeto del documento y hay cientos de selectores para comparar con cada evento burbujeado, esto puede comenzar a obstaculizar el rendimiento del manejo de eventos.
Por esta razón, desea configurar sus controladores de eventos delegados para que un controlador de eventos delegado esté tan cerca del objeto de destino como sea práctico. Esto significa que menos eventos aparecerán en cada controlador de eventos delegado, mejorando así el rendimiento. Poner todos los eventos delegados en el objeto del documento es el peor rendimiento posible porque todos los eventos burbujeados tienen que pasar por todos los controladores de eventos delegados y ser evaluados contra todos los posibles selectores de eventos delegados. Esto es exactamente por qué
.live()
está en desuso porque esto es lo que.live()
hizo y resultó ser muy ineficiente.Entonces, para lograr un rendimiento optimizado:
fuente
$(document).on('click', '[myCustomAttr]', function () { ... });
?document
, o vincular a selecciones más específicaspage:load
y desvincular estos eventospage:after-remove
? HmmmLa delegación de eventos es una técnica para escribir sus controladores antes de que el elemento realmente exista en DOM. Este método tiene sus propias desventajas y debe usarse solo si tiene tales requisitos.
¿Cuándo deberías usar la delegación de eventos?
¿Por qué no deberías usar la delegación de eventos?
PD: Incluso para contenido dinámico, no tiene que usar el método de delegación de eventos si está vinculando el controlador después de que el contenido se inserte en DOM. (Si el contenido dinámico se agrega, no se elimina / vuelve a agregar con frecuencia)
fuente
Aparentemente, la delegación de eventos se recomienda realmente ahora. al menos para vainilla js.
https://gomakethings.com/why-event-delegation-is-a-better-way-to-listen-for-events-in-vanilla-js/
"Rendimiento web # Parece que escuchar cada clic en el documento sería malo para el rendimiento, pero en realidad es más eficaz que tener un grupo de oyentes de eventos en elementos individuales".
fuente
Me gustaría agregar algunos comentarios y argumentos en contra a la respuesta de jfriend00. (principalmente solo mis opiniones basadas en mi instinto)
Si bien es cierto que el rendimiento podría ser un poco mejor si solo va a registrarse y participar en un solo elemento, creo que no se compara con los beneficios de escalabilidad que brinda la delegación. También creo que los navegadores (van a estar) manejando esto de manera cada vez más eficiente, aunque no tengo pruebas de ello. ¡En mi opinión, la delegación de eventos es el camino a seguir!
Estoy de acuerdo con esto. Si está 100% seguro de que un evento solo sucederá dentro de un contenedor, tiene sentido vincular el evento a este contenedor, pero aún argumentaría en contra de vincular eventos al elemento desencadenante directamente.
Esto simplemente no es cierto. Consulte este código Pen: https://codepen.io/pwkip/pen/jObGmjq
Ilustra cómo puede evitar que un usuario escriba escribiendo el evento de pulsación de tecla en el documento.
Me gustaría responder con esta cita de https://ehsangazar.com/optimizing-javascript-event-listeners-for-performance-e28406ad406c
Event delegation promotes binding as few DOM event handlers as possible, since each event handler requires memory. For example, let’s say that we have an HTML unordered list we want to bind event handlers to. Instead of binding a click event handler for each list item (which may be hundreds for all we know), we bind one click handler to the parent unordered list itself.
Además, buscar en Google
performance cost of event delegation google
devuelve más resultados a favor de la delegación de eventos.¿Dónde se documenta esto? Si eso es cierto, entonces jQuery parece estar manejando la delegación de una manera muy ineficiente, y luego mis contraargumentos solo deberían aplicarse a Vanilla JS.
Aún así: me gustaría encontrar una fuente oficial que respalde esta afirmación.
:: EDITAR ::
Parece que jQuery está haciendo burbujas de eventos de una manera muy ineficiente (porque son compatibles con IE8) https://api.jquery.com/on/#event-performance
Entonces, la mayoría de mis argumentos aquí solo son válidos para Vanilla JS y los navegadores modernos.
fuente