2012-01-24 34 views
33

¿Alguien me puede explicar por qué hay una diferencia en el orden en que se están ejecutando los controladores de eventos dependiendo de cómo se han adjuntado? En el siguiente ejemplo estoy usando los métodos .on() y .addEventListener() para manejar un evento específico en diferentes elementos DOM.jQuery .on(); vs JavaScript .addEventListener();

jsFiddle: http://jsfiddle.net/etsS2/

pensé que en este ejemplo particular, el orden en que los controladores de eventos va a ser ejecutado dependerá de la event-bubbling - por lo que a partir del evento original target y ascender a la document elemento.

document.getElementById('outer').addEventListener('mouseup', function (event) { 
//$('#outer').on('mouseup', function (event) { 
    alert('This alert should not show up!'); 
}, false); 

Si Descomentar la versión on(); todo funciona como se esperaba - ¿Existe una diferencia en la forma jQuery maneja sucesos contrarios a la llanura JavaScript?

Respuesta

22

Cuando usa .on() en el nivel del documento, está esperando que el evento continúe hasta ese punto. Ya se habrá llamado al controlador de eventos para cualquier contenedor intermedio.

Evento "burbujeo" es el proceso por el cual el navegador busca controladores de eventos registrados con los padres del elemento que fue el destinatario original real del evento. Funciona hacia arriba en el árbol DOM. El nivel del documento es último nivel marcado. Por lo tanto, su controlador registrado con .on() no se ejecutará hasta que se alcance ese nivel. Mientras tanto, el otro controlador de eventos en el nivel "exterior" se alcanza primero y el navegador lo ejecuta.

Por lo tanto, ese return false; en el controlador registrado con .on() es bastante inútil, como sería una llamada al event.stopPropagation(). Más allá de eso, mezclar el registro de manejador de eventos nativos con el trabajo que hará una biblioteca como jQuery es probablemente una muy mala idea a menos que sepas seriamente lo que estás haciendo.

Hubo a question asked almost exactly like this one hace un rato hoy.

+0

'return false' también hace' event.preventDefault() 'así como' event.stopPropagation() 'en un manejador de eventos jQuery. – Jasper

+0

La razón por la que he creado esta estructura se debe al hecho de que el elemento 'a.link' se agrega dinámicamente y de alguna manera tengo que evitar que el div' externo' se ocupe de ese evento en particular, ¿cómo puedo lograr eso? Entonces, básicamente, quiere decir que esto: $ (documento) .on ('mouseup', 'a.link' ...) es igual a esto: $ ('a.link'). Live ('mouseup', ...)? – MonkeyCoder

+1

Sí, la única forma en que un mecanismo como '.live()', '.delegate()', o el nuevo '.on()' puede funcionar es por burbujeo, y el burbujeo funciona desde adentro hacia afuera. En su lugar, podría asegurarse de que los detectores de eventos para los elementos añadidos dinámicamente se vinculen directamente a los elementos cuando se agregan al DOM. – Pointy

12

mirada a la versión addEventListener:

document.getElementById('outer').addEventListener('mouseup', function (event) { 
    alert('This alert should not show up!'); 
}, false); 

que funciona bien porque el tercer argumento es useCapture, que especifica si o no la fase de captura del evento se debe utilizar.

Al cambiar a la versión de jQuery:

$('#outer').on('mouseup', function (event) { 
    alert('This alert should not show up!'); 
}, false); 

Creo que lo que está sucediendo es el tercer argumento simplemente anulaciones la función de controlador de eventos y hace que el controlador de eventos para hacer nada más que return false; que no sea claramente lo que debe suceder

Desde el jQuery docs (énfasis añadido):

Una función que se ejecuta cuando se activa el evento. El valor falso es también permitido como una abreviatura de una función que simplemente devuelve falso.

Retire el argumento false y la versión de jQuery funcionará correctamente también:

$('#outer').on('mouseup', function (event) { 
    alert('This alert should not show up!'); 
}); 

Tenga en cuenta que la alert debe aparecer, por lo que el enfoque addEventListener está funcionando correctamente. Ver la respuesta de @ Pointy de por qué es eso.