多事件监听器的顺序

时间:2012-03-01 07:58:27

标签: javascript-events prototypejs

使用Prototype处理点击事件时,我遇到了一个奇怪的问题。如果单击下面代码中的按钮,它将触发三个警报:“单击1”,“单击2”和“单击3”。现代浏览器将按照它们注册的顺序调用侦听器,而IE8(也可能是旧的IE版本)将以相反的顺序调用它们。我发现这很奇怪,因为我认为Prototype维护并执行了一个侦听器队列,这应该是浏览器独立的。这不是这样吗?如果没有,事件监听器是否应按某种顺序运行,或者它们是异步的,因此它们的顺序无关紧要?

    <button id="button">Click me</button>
    <script type="text/javascript">
        $('button').observe('click', function(event) {
            alert('Click 1');
        });
        $('button').observe('click', function(event) {
            alert('Click 2');
        });
        $('button').observe('click', function(event) {
            alert('Click 3');
        });
    </script>

3 个答案:

答案 0 :(得分:15)

Prototype依赖于浏览器的订单底层触发机制(并非所有库都可以,见下文)。事件处理程序被触发的顺序最初不是由DOM事件保证的。来自DOM2 Events specification

  

虽然EventListeners上的所有EventTarget都可以保证由EventTarget收到的任何事件触发,但是没有规定它们将接收的顺序有关EventListeners上其他EventTarget的事件。

绝大多数浏览器实施(Chrome,Firefox,Opera等),包括IE9,都会按照附加顺序触发处理程序。 IE8和更早版本以相反的方式做到了。

较新的DOM3 event spec仍然是一项正在进行中的工作,它引入了按注册顺序触发它们的要求(大多数浏览器都这样做):

  

接下来,实现必须确定当前目标的候选事件侦听器。这必须是已按注册顺序在当前目标上注册的所有事件侦听器的列表。

......这可能是IE9为什么会这样做的原因之一(IE9显着提高了Microsoft对事件标准的支持,添加addEventListener等)。

一些JavaScript库(例如jQuery) do 保证订单,无论浏览器如何,每个元素每个事件只附加一个处理程序,并维护自己的用户代码处理程序列表。< / p>

答案 1 :(得分:1)

作为@ T.J的格式化评论。克劳德的答案,我测试了哪些现代浏览器实际上按照注册顺序触发了听众。

2016-10-06:结果是所有以下浏览器都这样做: chrome 53,firefox 49,safari 9,opera 40,ie 11和edge 13通过mac host上的virtualbox。

我的测试代码可以在这里找到:https://github.com/lingtalfi/browsers-behaviours/blob/master/listeners-execution-order/listeners.md

答案 2 :(得分:0)

根据这个bug report,它似乎是一个现有的错误,并且它实际上与浏览器有关。

总结报告:

它取决于浏览器,但有些用户(如海报)希望事件按顺序触发。错误条目在某一时刻被更改为文档更改(以通知用户订单实际上未指定),但错误仍然是开放的,因此我假设它尚未在文档中修复。