Estoy tratando de comprender esta diferencia específica entre las directas y delegadas controladores de eventos utilizando el jQuery .on () método . Específicamente, la última oración en este párrafo:
Cuando
selector
se proporciona a, el controlador de eventos se denomina delegado . No se llama al controlador cuando el evento ocurre directamente en el elemento enlazado, sino solo para los descendientes (elementos internos) que coinciden con el selector. jQuery burbujea el evento desde el destino del evento hasta el elemento donde está conectado el controlador (es decir, el elemento más interno al más externo) y ejecuta el controlador para cualquier elemento a lo largo de esa ruta que coincida con el selector.
¿Qué quiere decir con "ejecuta el controlador para cualquier elemento"? Hice una página de prueba para experimentar con el concepto. Pero las dos construcciones siguientes conducen al mismo comportamiento:
$("div#target span.green").on("click", function() {
alert($(this).attr("class") + " is clicked");
});
o,
$("div#target").on("click", "span.green", function() {
alert($(this).attr("class") + " is clicked");
});
¿Quizás alguien podría referirse a un ejemplo diferente para aclarar este punto? Gracias.
Respuestas:
Caso 1 (directo):
== ¡Hola! Quiero que cada span.green dentro del div # target escuche: cuando te hagan clic, haz X.
Caso 2 (delegado):
== ¡Hola, div # target! Cuando haga clic en cualquiera de los elementos secundarios que son "span.green", haga una X con ellos.
En otras palabras...
En el caso 1, cada uno de esos tramos ha recibido instrucciones individuales. Si se crean nuevos tramos, no habrán escuchado las instrucciones y no responderán a los clics. Cada lapso es directamente responsable de sus propios eventos.
En el caso 2, solo el contenedor ha recibido las instrucciones; es responsable de notar los clics en nombre de sus elementos secundarios. El trabajo de captura de eventos ha sido delegado . Esto también significa que la instrucción se llevará a cabo para los elementos secundarios que se creen en el futuro.
fuente
on()
permite dos argumentos cuando eso sería lo mismo que usarclick()
?e.target
será el objetivo inicial del evento de clic (puede ser un nodo hijo sispan.green
tiene hijos). Desde el interior del controlador, debe usar lathis
referencia. Ver este violín .La primera forma,
$("div#target span.green").on()
vincula un controlador de clics directamente a los intervalos que coinciden con el selector en el momento en que se ejecuta el código. Esto significa que si se agregan otros tramos más tarde (o si se cambia su clase para que coincida), se han perdido y no tendrán un controlador de clics. También significa que si luego elimina la clase "verde" de uno de los tramos, su controlador de clics continuará ejecutándose: jQuery no realiza un seguimiento de cómo se asignó el controlador y verifica si el selector aún coincide.La segunda forma,
$("div#target").on()
vincula un controlador de clic a los div (s) que coinciden (de nuevo, esto es contra los que coinciden en ese momento), pero cuando se produce un clic en algún lugar del div, la función del controlador solo se ejecutará si el clic ocurrió no solo en el div sino en un elemento hijo que coincide con el selector en el segundo parámetro a.on()
"span.green". Hecho de esta manera, no importa cuándo se crearon esos tramos secundarios, al hacer clic en ellos se ejecutará el controlador.Entonces, para una página que no agrega o cambia dinámicamente su contenido, no notará una diferencia entre los dos métodos. Si agrega dinámicamente elementos secundarios adicionales, la segunda sintaxis significa que no tiene que preocuparse por asignarles controladores de clics porque ya lo hizo una vez en el elemento primario.
fuente
La explicación de N3dst4 es perfecta. En base a esto, podemos suponer que todos los elementos secundarios están dentro del cuerpo, por lo tanto, solo necesitamos usar esto:
Funciona con evento directo o delegado.
fuente
$('body').on()
delegación de.element
debería comportarse exactamente igual que la nativadocument.body.addEventHandler()
con unif (Event.target.className.matches(/\belement\b/))
en la devolución de llamada. Puede ser un poco más lento en jquery debido a la$.proxy
sobrecarga, pero no me cite al respecto.Tangencial al OP, pero el concepto que me ayudó a desentrañar la confusión con esta característica es que los elementos vinculados deben ser padres de los elementos seleccionados .
.on
..on()
.La delegación no funciona como .find (), seleccionando un subconjunto de los elementos enlazados. El selector solo se aplica a elementos secundarios estrictos.
es muy diferente de
En particular, para obtener las ventajas @ N3dst4 sugiere "elementos que se crearán en el futuro", el elemento enlazado debe ser un padre permanente . Entonces los niños seleccionados pueden ir y venir.
EDITAR
Lista de verificación de por qué delegado
.on
no funcionaRazones difíciles por las que
$('.bound').on('event', '.selected', some_function)
puede no funcionar:.on()
.stopPropagation()
.(Omitiendo razones menos difíciles, como un selector mal escrito).
fuente
Escribí una publicación con una comparación de eventos directos y delegados. Comparo js puro pero tiene el mismo significado para jquery que solo lo encapsula.
La conclusión es que el manejo de eventos delegados es para una estructura DOM dinámica donde se pueden crear elementos enlazados mientras el usuario interactúa con la página (sin necesidad de enlaces nuevamente), y el manejo directo de eventos es para elementos DOM estáticos, cuando sabemos que la estructura no cambiará.
Para obtener más información y una comparación completa: http://maciejsikora.com/standard-events-vs-event-delegation/
El uso de controladores siempre delegados, que veo que está muy de moda actualmente, no es la forma correcta, muchos programadores lo usan porque "debería usarse", pero la verdad es que los controladores de eventos directos son mejores para alguna situación y la elección de qué método usar debe ser compatible por conocimiento de las diferencias.
fuente