委托活动

让我们从示例开始。这是一个非常简单的 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,并确保它们仍然可以工作。