簡體   English   中英

在瀏覽器中觸發事件時,事件處理程序在什么時候確定?

[英]At what point do the event handlers get determined when an event has been fired in the browser?

我最近閱讀了很多關於事件循環和它所具有的不同隊列(作業/宏任務隊列、微任務隊列、渲染隊列)及其優先級的信息。 但是我仍然無法完全理解一件事,假設用戶一個接一個地快速觸發 2 個事件。 然后兩個事件處理程序將被排入作業隊列並以正確的順序執行。 但是,如果第一個事件處理程序進行了一些繁重的計算並阻塞了主線程一段時間,但它也以改變 UI 的方式操作 DOM,以便用戶第二次單擊的元素被刪除並替換為一些其他也注冊了點擊事件的 dom 元素。

然后,如果我正確理解了這個過程,一旦第一個事件處理程序完成執行,所有微任務都會被執行並且微任務隊列被清空。 然后渲染隊列被清空,瀏覽器重新繪制。 這是我的實際問題,第二個事件處理程序是根據 UI 的新狀態執行,還是根據單擊時存在的元素執行?

我嘗試了這一點( https://jsfiddle.net/jsx73t6c/4/ ),每個按鈕都有一個注冊了單擊事件處理程序的按鈕,該處理程序記錄到單擊相應按鈕的控制台。 我在按鈕 1 和按鈕 2 上快速單擊。按鈕 1 的處理程序執行一個大循環,因此主線程被阻塞一段時間,然后刪除按鈕 2。由於按鈕 2 被刪除,它的位置是按鈕 3,我最終得到 2控制台日志指示按鈕 1 和按鈕 3 已被單擊,即使在單擊我的鼠標時它位於按鈕 1 和按鈕 2 上。似乎事件處理程序已在隊列中注冊,但單擊發生的元素已確定稍后需要處理 click 事件並觸發已注冊的事件處理程序。 對我來說,這種行為比在點擊時根據 DOM 的狀態確定被點擊的元素更有意義,並且是一種更可預測的行為。 但我仍然不確定我的示例中的行為是否始終得到保證。

const button2 = getButton(2);
const button3 = getButton(3);

const removeButton2 = () => button2.parentElement.removeChild(button2);

button2.addEventListener("click", () => console.log("button 2 clicked"));

button3.addEventListener("click", () => console.log("button 3 clicked"));

button1.addEventListener("click", () => {
  console.log("button 1 clicked");

  const fragment = document.createDocumentFragment();
  for (let i = 0; i < 70_000; i++) {
    const a = document.createElement("a");
    a.innerHTML = "text " + i;
    fragment.appendChild(a);
  }

  document.documentElement.appendChild(fragment);
  removeButton2();
});
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <button id="button-1">button 1</button>
    <button id="button-2">button 2</button>
    <button id="button-3">button 3</button>
  </body>
</html>

我知道這種現實世界的場景不太可能在瀏覽器的當前狀態下偶然發生,在這種狀態下一切都發生得如此之快,但希望能獲得更多關於該主題的光線和資源。

這將取決於實現,即使所有現代 UA 都公開相同的行為。 例如,在舊的 IE 中,它對所有內容都使用單個進程,您的點擊事件在被阻止時將被忽略。

現代瀏覽器現在有許多輔助進程,因此它們可以處理它(瀏覽器進程可以保留消息,直到渲染器准備好處理它)。
所以是的,在當前的主流瀏覽器中,只有當第一個回調完成時,渲染器才會處理您的事件,這就是實際的 DOM 事件將被構造的時候,因此它將使用更新的 DOM 樹。

您可以看到這個 Chromium 設計文檔,其中談到了一點: https ://www.chromium.org/developers/design-documents/displaying-a-web-page-in-chrome/#life-of-a-mouse -click-message ,這是關於 IPC 消息傳遞的一般信息: https ://www.chromium.org/developers/design-documents/inter-process-communication/

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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