委託活動

讓我們從示例開始。這是一個非常簡單的 HTML 示例。

示例 HTML

<html>
    <head>
    </head>
    <body>
        <ul>
            <li>
                <a href="some_url/">Link 1</a>
            </li>
            <li>
                <a href="some_url/">Link 2</a>
            </li>
            <li>
                <a href="some_url/">Link 3</a>
            </li>
        </ul>
    </body>
</html>

問題

現在在這個例子中,我們想要為所有 <a> 元素新增一個事件監聽器。問題是此示例中的列表是動態的。隨著時間的推移,新增和刪除 <li> 元素。但是,頁面不會在更改之間重新整理,這將允許我們使用簡單的單擊事件偵聽器來連結物件(即 $('a').click())。

我們遇到的問題是如何將事件新增到來去的 <a> 元素中。

背景資訊 - 事件傳播

委託事件只能由於事件傳播(通常稱為事件冒泡)而發生。每當一個事件被觸發時,它將一直冒泡(到文件根目錄)。它們事件的處理委託給不變的祖先元素,因此命名為委託事件。

因此,在上面的示例中,單擊 <a> 元素連結將按以下順序觸發這些元素中的 click 事件:

  • 一個
  • UL
  • 身體
  • HTML
  • 檔案根

知道什麼事件冒泡,我們可以捕獲一個通過我們的 HTML 傳播的通緝事件。

在這個例子中捕獲它的一個好地方是 <ul> 元素,因為該元素不是動態的:

$('ul').on('click', 'a', function () {
  console.log(this.href); // jQuery binds the event function to the targeted DOM element
                          // this way `this` refers to the anchor and not to the list
  // Whatever you want to do when link is clicked
});

在上面:

  • 我們有’ul’這個事件監聽器的接收者
  • 第一個引數(‘click’)定義了我們要檢測的事件。
  • 第二個引數(‘a’)用於宣告事件需要源自的位置(此事件偵聽器的收件人下的所有子元素,ul)。
  • 最後,第三個引數是在滿足第一個和第二個引數要求時執行的程式碼。

詳細解決方案如何工作

  1. 使用者點選 <a> 元素
  2. 這會觸發 <a> 元素上的 click 事件。
  3. 事件開始冒泡到文件根目錄。
  4. 事件首先到 <li> 元素,然後到 <ul> 元素。
  5. 事件監聽器在 <ul> 元素附加事件監聽器時執行。
  6. 事件偵聽器首先檢測觸發事件。冒泡事件是點選,聽眾有點選,這是一個傳球。
  7. 監聽器檢查嘗試將第二個引數(‘a’)與氣泡鏈中的每個項匹配。由於鏈中的最後一項是’a’,這與過濾器匹配,這也是一個過程。
  8. 第三個引數中的程式碼使用匹配的專案執行,因為它是 this。如果該函式不包含對 stopPropagation() 的呼叫,則該事件將繼續向上傳播到根(document)。

注意:如果沒有合適的不變的祖先/方便,你應該使用 document。作為習慣,不要使用'body',原因如下:

  • body 有一個 bug,與樣式有關,這可能意味著滑鼠事件不會冒泡。這取決於瀏覽器,並且可以在計算的身高為 0 時發生(例如,當所有子元素具有絕對位置時)。滑鼠事件總是起泡到 document
  • document 始終存在於你的指令碼中,因此你可以將委派的處理程式附加到支援 DOM 的處理程式之外的 document,並確保它們仍然可以工作。