一个文档中有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;
};
为了确保click事件不会被其他脚本覆盖,我切换到
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)怎么办?
最佳答案
如果您可以先注册处理程序,则可以先进行注册,前提是您使用的浏览器正确实现了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
不会停止调用同一元素上的其他处理程序。从the spec:(我的重点。)
3.停止调用同一元素上的其他处理程序
自然地,对于DOM0来说并没有出现这种情况,因为在同一元素上不可能有相同事件的其他处理程序。 :-)
据我所知,在DOM2中无法做到这一点,但是DOM3为我们提供了
stopImmediatePropagation
:document.addEventListener("click", function(e) {
e.stopImmediatePropagation();
}, false);
一些库为通过该库连接的处理程序提供了此功能(甚至在非DOM3系统(如IE8)上),请参见下文。
4.调用处理程序的顺序
再说一次,没有与DOM0相关的东西,因为不可能有其他处理程序。
在DOM2中,规范明确指出不能保证调用附加到元素的处理程序的顺序。但是DOM3改变了这一点,说处理程序是按照注册时的顺序调用的。
首先,从DOM2 Section 1.2.1:
但这被DOM3 Section 3.1取代:
(我的重点。)
如果您将事件与库连接起来,则某些库可以保证顺序。
还值得注意的是,在Microsoft DOM2的前身(例如
attachEvent
)中,它与DOM3的顺序相反:处理程序以相反的注册顺序调用。因此,将#3和#4放在一起,如果可以先注册您的处理程序,则会首先调用它,并且可以使用
stopImmediatePropagation
防止其他处理程序被调用。只要浏览器正确实现DOM3。所有这一切(包括IE8和更早版本甚至都没有实现DOM2事件,更不用说DOM3的事实)是人们使用jQuery之类的库的原因之一,其中某些库确实保证了顺序(只要一切都通过钩住处理程序即可)库),并提供了一些方法来停止调用同一元素上的其他处理程序。 (例如,使用jQuery时,顺序就是它们附加的顺序,您可以使用
stopImmediatePropagation
停止对其他处理程序的调用。但是我并不想在这里出售jQuery,只是在解释一些库提供了比基本的DOM内容。)