委托活动
让我们从示例开始。这是一个非常简单的 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)。
- 最后,第三个参数是在满足第一个和第二个参数要求时运行的代码。
详细解决方案如何工作
- 用户点击
<a>
元素 - 这会触发
<a>
元素上的 click 事件。 - 事件开始冒泡到文档根目录。
- 事件首先到
<li>
元素,然后到<ul>
元素。 - 事件监听器在
<ul>
元素附加事件监听器时运行。 - 事件侦听器首先检测触发事件。冒泡事件是点击,听众有点击,这是一个传球。
- 监听器检查尝试将第二个参数(‘a’)与气泡链中的每个项匹配。由于链中的最后一项是’a’,这与过滤器匹配,这也是一个过程。
- 第三个参数中的代码使用匹配的项目运行,因为它是
this
。如果该函数不包含对stopPropagation()
的调用,则该事件将继续向上传播到根(document
)。
注意:如果没有合适的不变的祖先/方便,你应该使用 document
。作为习惯,不要使用'body'
,原因如下:
body
有一个 bug,与样式有关,这可能意味着鼠标事件不会冒泡。这取决于浏览器,并且可以在计算的身高为 0 时发生(例如,当所有子元素具有绝对位置时)。鼠标事件总是起泡到document
。document
始终存在于你的脚本中,因此你可以将委派的处理程序附加到支持 DOM 的处理程序之外的document
,并确保它们仍然可以工作。