2012-01-24 36 views
33

有人能解释一下,为什么事件处理程序的执行顺序有所不同,具体取决于它们的连接方式?在下面的示例中,我使用.on().addEventListener()方法处理不同DOM元素上的特定事件。jQuery .on(); vs JavaScript .addEventListener();

的jsfiddlehttp://jsfiddle.net/etsS2/

我认为,在这个特殊的例子的顺序事件处理程序将要执行将取决于event-bubbling - 所以从原始的事件target开始,移动到document元素。

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

如果我取消了on();版本一切正常 - 有没有在如何处理jQuery违背纯JavaScript事件有区别吗?

回答

22

当您在文档级别使用.on()时,您正在等待事件一直冒泡到该点。任何中间容器的事件处理程序都已被调用。

事件“冒泡”是浏览器查找事件处理程序的过程,该事件处理程序向事件的实际原始收件人的元素的父项进行了注册。它在DOM树中向上工作。文档级别是最后级别检查。因此,注册.on()的处理程序将不会运行,直到达到该级别。同时,首先到达“外层”级别的其他事件处理程序,并由浏览器执行。

因此,在.on()注册的处理程序中的return false;几乎没有任何用处,因为将调用event.stopPropagation()。除此之外,将本机事件处理程序注册与像jQuery这样的库所做的工作混合起来可能是一个非常糟糕的主意,除非您真正了解自己在做什么。

就在不久前的a question asked almost exactly like this one

+0

'return false'在jQuery事件处理程序中也会执行'event.preventDefault()'和'event.stopPropagation()'。 – Jasper

+0

我创建这个结构的原因是因为'a.link'元素是动态添加的,而且我需要阻止'outer' div处理那个特定事件 - 我该如何实现?所以基本上你的意思是:$(document).on('mouseup','a.link'...)等于:$('a.link')。live('mouseup',... )? – MonkeyCoder

+1

是的 - 像'.live()','.delegate()'或新的'.on()'这样的机制可以工作的唯一方式是通过冒泡,冒泡从内到外都可以工作。您可以确保动态添加元素的事件侦听器在添加到DOM时直接绑定到元素。 – Pointy

12

看那addEventListener版本:

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

,由于第三个参数是useCapture,它指定是否应使用该事件的捕获阶段工作正常。

当您切换到了jQuery版本:

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

我认为正在发生的事情是第三个参数只是覆盖事件处理函数,并导致事件处理程序做什么,但return false;这显然不是什么意思发生。

jQuery docs(强调):

函数时被触发的事件而执行。 False的值为 也允许作为简单返回 false的函数的简写。

取出false参数和jQuery的版本将正常工作太:

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

注意,alert应该显示出来,所以addEventListener办法正常工作。查看@ Pointy的答案是为什么。