如果我希望我的脚本完全控制点击事件(比如始终返回 false,而忽略其他脚本中定义的事件)怎么办?
如果您可以先注册您的处理程序,在他们注册之前,您可以这样做,前提是您使用的浏览器正确实现了 DOM3 事件(除非它是 IE8 或更早版本,否则它可能会这样做)。
这里(至少)涉及四件事:
防止默认。
停止传播到祖先元素。
停止调用 same 元素上的其他处理程序。
处理程序的调用顺序。
按顺序:
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 不会阻止调用同一元素上的其他处理程序。来自the spec:
stopPropagation 方法用于防止在事件流期间进一步传播事件。如果任何EventListener 调用此方法,则事件将停止在树中传播。 事件将在事件流停止之前完成向当前EventTarget 上的所有侦听器的调度。
(我的重点。)
3。停止调用 same 元素上的其他处理程序
当然,DOM0 不会出现这种情况,因为对于同一元素上的同一事件,不可能有 其他处理程序。 :-)
据我所知,在 DOM2 中没有办法做到这一点,但 DOM3 给了我们stopImmediatePropagation:
document.addEventListener("click", function(e) {
e.stopImmediatePropagation();
}, false);
一些库为通过库连接的处理程序提供此功能(甚至在 IE8 等非 DOM3 系统上),见下文。
4。调用处理程序的顺序
同样,与 DOM0 无关,因为不可能有其他处理程序。
在 DOM2 中,规范明确说,附加到元素的处理程序被调用的顺序并不能保证;但是 DOM3 改变了这一点,表示处理程序按照它们注册的顺序被调用。
首先,来自 DOM2 Section 1.2.1:
尽管EventTarget 上的所有EventListeners 都保证会被该EventTarget 接收到的任何事件触发,但没有指定它们接收事件的顺序相对于另一个EventListenersEventTarget。
但这已被 DOM3 Section 3.1 取代:
接下来,实现必须确定当前目标的候选事件侦听器。这必须是按注册顺序在当前目标上注册的所有事件侦听器的列表。
(我的重点。)
如果您将事件与库挂钩,一些库会保证顺序。
还值得注意的是,在 Microsoft 的 DOM2 前身(例如,attachEvent)中,它与 DOM3 的顺序相反:处理程序以 reverse 的注册顺序调用。
所以把#3 和#4 放在一起,如果你可以先注册你的处理程序,它会先被调用,你可以使用stopImmediatePropagation 来防止其他处理程序被调用。前提是浏览器正确实现了 DOM3。
所有这些(包括 IE8 和更早版本甚至不实现 DOM2 事件,更不用说 DOM3)是人们使用 jQuery 之类的库的原因之一,其中一些确实保证了顺序(只要一切都在连接他们的处理程序通过有问题的库),并提供了阻止同一元素上的其他处理程序被调用的方法。 (例如,对于 jQuery,顺序是它们附加的顺序,您可以使用 stopImmediatePropagation 来停止对其他处理程序的调用。但我不想在这里出售 jQuery,只是解释一些库提供更多功能比基本的 DOM 东西。)