我在使用 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>
最佳答案
Prototype 依赖于浏览器的底层触发机制来进行排序(并非所有库都这样做,请参见下文)。 DOM 事件最初并不能保证触发事件处理程序的顺序(但请继续阅读)。来自DOM2 Events specification :
Although all
EventListeners
on theEventTarget
are guaranteed to be triggered by any event which is received by thatEventTarget
, no specification is made as to the order in which they will receive the event with regards to the otherEventListeners
on theEventTarget
.
绝大多数浏览器实现(Chrome、Firefox、Opera 等),包括 IE9,都按照它们附加的顺序触发处理程序。 IE8 和更早版本以相反的方式执行此操作。
较新的(现在非常成熟)DOM3 event spec添加了按注册顺序触发它们的要求(大多数浏览器都这样做):
Next, the implementation must determine the current target's candidate event listeners. This must be the list of all event listeners that have been registered on the current target in their order of registration.
...这可能是 IE9 现在这样做的部分原因(IE9 显着改进了 Microsoft 对事件标准的支持,添加了 addEventListener
等)。
某些 JavaScript 库(例如 jQuery)确实通过为每个元素的每个事件仅附加一个处理程序并维护它们自己的要触发的用户代码处理程序列表来保证顺序,而不管浏览器如何。
关于javascript - 多个事件监听器的顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9512551/