文档中有2个脚本
// my_script.js goes first
document.onclick = function() {
alert("document clicked");
};
// other_script.js comes after
// this overrides the onclick of my script,
// and alert will NOT be fired
document.onclick = function() {
return false;
};
为确保我的点击事件不被其他脚本覆盖,我切换到addEventListener
。
// my_script.js goes first
document.addEventListener("click", function() {
alert("document clicked");
}, false);
// other_script.js comes after
document.addEventListener("click", function() {
return false;
}, false);
现在我又得到了一个问题。由于第二个代码中的return false
是在alert
之后定义的,为什么它不会阻止警报被调用?
如果我希望我的脚本能够完全控制click事件(比如忽略其他脚本中定义的事件,则一直返回false)会怎样?
答案 0 :(得分:46)
如果我希望我的脚本能够完全控制click事件(比如忽略其他脚本中定义的事件,则一直返回false)会怎样?
如果你可以先注册你的处理程序,那么你可以这样做,只要你正在使用的浏览器正确地实现了DOM3事件(除非它是IE8或更早版本,它可能会这样做。)
这里涉及(至少)四件事:
防止默认。
停止传播到祖先元素。
停止调用相同元素上的其他处理程序。
调用处理程序的顺序。
按顺序:
这是来自DOM0处理程序的return false
。 (详情:The Story on Return False。)DOM2和DOM3中的等价物是preventDefault
:
document.addEventListener("click", function(e) {
e.preventDefault();
}, false);
防止默认值可能与您正在做的事情无关,但由于您在DOM0处理程序中使用return false
,并且这会阻止默认值,因此我将其包含在此处以保证完整性。< / p>
DOM0处理程序无法执行此操作。 DOM2可以通过stopPropagation
:
document.addEventListener("click", function(e) {
e.stopPropagation();
}, false);
但是stopPropagation
并没有阻止同一个元素被调用的其他处理程序。来自the spec:
使用
stopPropagation
方法防止在事件流期间进一步传播事件。如果任何EventListener
调用此方法,则事件将停止在树中传播。 事件将在事件流程停止之前完成对当前EventTarget
的所有侦听器的调度。
(我的重点。)
当然,DOM0没有出现这种情况,因为在同一个元素上,同样的事件不能 其他处理程序。 : - )
据我所知,在DOM2中无法做到这一点,但DOM3为我们提供了stopImmediatePropagation
:
document.addEventListener("click", function(e) {
e.stopImmediatePropagation();
}, false);
有些库提供此功能(即使在IE8等非DOM3系统上),也可以通过库连接处理程序,如下所示。
同样,不是与DOM0相关的东西,因为没有其他处理程序。
在DOM2中,规范显式表示不保证调用附加到元素的处理程序的顺序;但是DOM3改变了这一点,说处理程序是按照它们注册的顺序调用的。
首先,来自DOM2 Section 1.2.1:
虽然
EventListeners
上的所有EventTarget
都可以保证由EventTarget
收到的任何事件触发,但是没有规定它们将接收的顺序有关EventListeners
上其他EventTarget
的事件。
但这已被DOM3 Section 3.1取代:
接下来,实现必须确定当前目标的候选事件侦听器。这必须是已按照注册顺序>>在当前目标上注册的所有事件侦听器的列表。
(我的重点。)
如果您将事件与库挂钩,某些库可以保证订单。
值得注意的是,在Microsoft的DOM2的前身(例如,attachEvent
)中,它与DOM3的顺序相反:处理程序以 reverse 注册顺序调用。
所以将#3和#4放在一起,如果你可以先注册你的处理程序,它将首先被调用,你可以使用stopImmediatePropagation
来阻止其他处理程序被调用。如果浏览器正确实现DOM3。
所有这一切(包括IE8及其早期甚至不实现DOM2事件,更不用说DOM3)的事实是人们使用像jQuery这样的库的一个原因,其中一些确实保证了订单(只要一切都在挂钩)他们的处理程序通过相关的库)并提供方法来阻止其他处理程序在相同的元素被调用。 (例如,使用jQuery,顺序是它们被附加的顺序,你可以使用stopImmediatePropagation
来停止对其他处理程序的调用。但我不是想在这里销售jQuery,只是解释一些库提供比基本DOM内容更多的功能。)