如果我想让我的脚本完全控制点击事件(就像无视其他脚本中定义的事件,总是返回false),该怎么办?
如果你能在他们注册之前先注册你的处理程序,你就可以这样做,前提是你使用的浏览器正确实现了DOM3事件(除非它是IE8或更早版本)。
这里涉及到(至少)四个方面:
防止默认行为。
阻止传播到祖先元素。
阻止调用同一元素上的其他处理程序。
处理程序被调用的顺序。
按照顺序:
1. 防止默认行为
这是DOM0处理程序中的return false所做的。 (详情:The Story on Return False)。在DOM2和DOM3中,相当于使用preventDefault
:
document.addEventListener("click", function(e) {
e.preventDefault();
}, false);
阻止默认行为可能与你正在做的事情并不相关,但由于你在DOM0处理程序中使用了return false
,这会防止默认行为发生,因此我在这里包含它以完整性起见。
2. 阻止事件冒泡到祖先元素
DOM0处理程序无法实现此功能。DOM2可以通过stopPropagation
来实现:
document.addEventListener("click", function(e) {
e.stopPropagation();
}, false);
但是,
stopPropagation
不能阻止在同一元素上调用的其他处理程序。根据
规范:
“
stopPropagation
方法用于在事件流期间防止事件进一步传播。如果此方法由任何
EventListener
调用,则事件将停止通过树进行传播。事件流停止之前,事件将完成对当前上的所有侦听器的分派。”
(强调是我的。)
3. 阻止在同一元素上调用其他处理程序
自然地,这在DOM0中没有出现,因为不能在同一元素上有相同事件的其他处理程序。 :-)
据我所知,在DOM2中没有办法做到这一点,但是DOM3为我们提供了
stopImmediatePropagation
:
document.addEventListener("click", function(e) {
e.stopImmediatePropagation();
}, false);
一些库提供此功能(即使在非 DOM3 系统(如 IE8)上连接到库的处理程序),请参见下面。
4. 调用处理程序的顺序
再次强调,这与 DOM0 无关,因为不可能有其他处理程序。
在 DOM2 中,规范明确表示不能保证以附加到元素的处理程序的顺序进行调用; 但是 DOM3 更改了该规定,指出处理程序按照注册它们的顺序进行调用。
首先来自 DOM2第1.2.1节:
虽然将接收到的任何事件都保证触发事件目标上的所有 EventListeners,但是没有规定它们将根据其他 EventListeners 接收事件的顺序接收该事件。
但是,DOM3第3.1节取代了它:
接下来,实现必须确定当前目标的候选事件侦听器。 这必须是已在当前目标上注册的所有事件侦听器列表,按其注册顺序排列。
(我强调。)
一些库保证顺序,只要您使用库连接事件。
值得注意的是,在 Microsoft 的 DOM2 前身(例如,attachEvent
),与 DOM3 的顺序相反:处理程序按其注册的倒序调用。
因此,将#3和#4结合起来,如果您可以首先注册处理程序,则将首先调用它,并且您可以使用 stopImmediatePropagation
阻止调用其他处理程序。 前提是浏览器正确实现了 DOM3。
所有这些(包括 IE8 及更早版本甚至不实现 DOM2 事件,更不用说 DOM3 了)都是人们使用 jQuery 等库的原因之一,其中一些确保顺序(只要每个人都通过所涉及的库连接他们的处理程序),并且提供停止甚至调用同一元素上的其他处理程序的方法。 (例如,使用 jQuery,顺序是附加它们的顺序,而您可以使用 stopImmediatePropagation
来停止对其他处理程序的调用。 但我不是在这里销售 jQuery,只是解释一些库提供比基本 DOM 更多功能。)
e.stopImmediatePropagation();
有效。但它必须在任何其他事件侦听器之前定义。处理程序的执行顺序确实是从上到下,而不是像您引用的“不保证”的那样,在我的测试中至少如此。感谢您提供详细信息。 - user1643156