簡體   English   中英

多個 addEventListener 在 JavaScript 中如何工作?

[英]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 或更早版本,否則它可能會這樣做)。

這里涉及(至少)四件事:

  1. 防止默認。

  2. 停止傳播到祖先元素。

  3. 停止調用同一元素上的其他處理程序。

  4. 調用處理程序的順序。

為了:

1. 防止默認

這就是 DOM0 處理程序的return false所做的。 (詳細信息: 返回 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調用,則事件將停止在樹中傳播。 該事件將在事件流停止之前完成對當前EventTarget上的所有偵聽器的調度。

(我的重點。)

3. 停止調用同一元素上的其他處理程序

自然,這不會出現在 DOM0 上,因為在同一元素上不可能其他處理程序來處理同一事件。 :-)

據我所知,在 DOM2 中沒有辦法做到這一點,但 DOM3 給了我們stopImmediatePropagation

document.addEventListener("click", function(e) {
    e.stopImmediatePropagation();
}, false);

一些庫為通過庫連接的處理程序提供此功能(即使在非 DOM3 系統上,如 IE8),請參見下文。

4. 處理程序的調用順序

同樣,與 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM