[英]How do multiple addEventListener work in JavaScript?
一個文檔中有 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
之后定義的,為什么它不阻止 alert 被調用?
如果我希望我的腳本完全控制點擊事件(例如始終返回 false,而忽略其他腳本中定義的事件),該怎么辦?
如果我希望我的腳本完全控制點擊事件(例如始終返回 false,而忽略其他腳本中定義的事件),該怎么辦?
如果您可以先注冊您的處理程序,那么您就可以這樣做,前提是您使用的瀏覽器正確實現了 DOM3 事件(除非是 IE8 或更早版本,否則它可能會這樣做)。
這里涉及(至少)四件事:
防止默認。
停止傳播到祖先元素。
停止調用同一元素上的其他處理程序。
調用處理程序的順序。
為了:
這就是 DOM0 處理程序的return false
所做的。 (詳細信息: 返回 False 的故事。)DOM2 和 DOM3 中的等價物是preventDefault
:
document.addEventListener("click", function(e) {
e.preventDefault();
}, false);
防止默認值可能與您正在做的事情無關,但由於您在 DOM0 處理程序中使用了return false
,這會阻止默認值,為了完整起見,我將其包含在此處。
DOM0 處理程序無法做到這一點。 DOM2 的,通過stopPropagation
:
document.addEventListener("click", function(e) {
e.stopPropagation();
}, false);
但是stopPropagation
不會停止調用同一元素上的其他處理程序。 從規范:
stopPropagation
方法用於防止事件流期間事件的進一步傳播。 如果此方法被任何EventListener
調用,則事件將停止在樹中傳播。 該事件將在事件流停止之前完成對當前EventTarget
上的所有偵聽器的調度。
(我的重點。)
自然,這不會出現在 DOM0 上,因為在同一元素上不可能有其他處理程序來處理同一事件。 :-)
據我所知,在 DOM2 中沒有辦法做到這一點,但 DOM3 給了我們stopImmediatePropagation
:
document.addEventListener("click", function(e) {
e.stopImmediatePropagation();
}, false);
一些庫為通過庫連接的處理程序提供此功能(即使在非 DOM3 系統上,如 IE8),請參見下文。
同樣,與 DOM0 無關,因為不可能有其他處理程序。
在 DOM2 中,規范明確表示不保證調用附加到元素的處理程序的順序; 但是 DOM3 改變了這一點,說處理程序按照它們注冊的順序被調用。
首先,來自 DOM2 Section 1.2.1 :
盡管
EventTarget
上的所有EventListeners
都保證由該EventTarget
接收的任何事件觸發,但沒有指定它們將接收事件的順序與EventTarget
上的其他EventListeners
。
但這被 DOM3第 3.1 節取代:
接下來,實現必須確定當前目標的候選事件偵聽器。 這必須是按注冊順序在當前目標上注冊的所有事件偵聽器的列表。
(我的重點。)
一些庫可以保證順序,前提是您將事件與庫連接起來。
還值得注意的是,在 Microsoft DOM2 的前身(例如, attachEvent
)中,它與 DOM3 的順序相反:以注冊的相反順序調用處理程序。
因此,將 #3 和 #4 放在一起,如果您可以先注冊您的處理程序,它將首先被調用,您可以使用stopImmediatePropagation
來防止其他處理程序被調用。 前提是瀏覽器正確實現了 DOM3。
所有這些(包括 IE8 及更早版本甚至不實現 DOM2 事件,更不用說 DOM3)是人們使用像 jQuery 這樣的庫的原因之一,其中一些庫確實保證了順序(只要一切都通過有問題的庫)並提供方法來停止調用同一元素上的其他處理程序。 (例如,對於 jQuery,順序是它們被附加的順序,您可以使用stopImmediatePropagation
來停止對其他處理程序的調用。但我並不想在這里推銷 jQuery,只是解釋一些庫提供的功能比基本的 DOM 東西。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.