在 JavaScript 中,事件捕获是事件传播模型的初始阶段,在这一阶段事件从文档树的根部传播到目标元素。在此期间,浏览器会在事件到达目标元素之前,在目标元素的祖先元素上捕获事件。
事件捕获和事件冒泡是 JavaScript 事件传播模型的两个阶段。在事件捕获中,浏览器从文档层次结构的根部开始捕获并触发事件,一直向下传播到目标元素。另一方面,事件冒泡发生在事件到达目标元素之后,并从目标元素向上冒泡回到根部。
捕获适用于在事件到达目标元素之前,在较高层级的祖先元素上拦截和处理事件的情况,而冒泡则是默认行为,事件从目标元素向上传播。理解这两个阶段对于有效处理事件和控制事件流至关重要。
让我们来看看事件捕获的一些重要方面。
重要方面
方面 |
描述 |
阶段 |
事件捕获是事件传播模型的初始阶段。 |
方向 |
捕获按照元素层次结构的逆序发生,从文档树的根部到目标元素。 |
使用案例 |
在事件到达目标元素或触发任何冒泡阶段处理程序之前,在较高层级的祖先元素上处理事件有用。 |
注册 |
使用 addEventListener 的第三个参数注册事件监听器以启用捕获(例如,element.addEventListener('click', myFunction, true);)。 |
传播 |
在到达目标和冒泡阶段之前的自动传播。事件向下流动,触发每个祖先上的捕获阶段处理程序。 |
阻止默认行为 |
在捕获阶段使用 event.preventDefault() 来阻止事件到达目标前的默认行为。 |
阻止传播 |
在捕获阶段使用 event.stopPropagation() 来阻止事件进一步传播,防止它到达目标或触发冒泡阶段处理程序。 |
示例:基本的事件捕获
在这个例子中,我们有一个容器 div (container
) 和其中的一个按钮 (myButton
)。使用带有 true
参数的 addEventListener
添加了两个捕获阶段的事件监听器。当你点击按钮时,将显示两条捕获阶段的日志消息(Container clicked 和 Button clicked)。这展示了当事件从文档根部传播到目标元素时发生的捕获阶段。
<!DOCTYPE html>
<html>
<body>
<div id="container">
<button id="myButton">Click me!</button>
</div>
<div id = "output"></div>
<script>
const output = document.getElementById('output');
document.getElementById('container').addEventListener('click', function(event) {
output.innerHTML += 'Capturing phase - Container clicked' + "<br>";
}, true);
document.getElementById('myButton').addEventListener('click', function(event) {
output.innerHTML += 'Capturing phase - Button clicked' + "<br>";
}, true);
</script>
</body>
</html>
示例:阻止默认行为
在这个例子中,我们有一个超链接(<a>
),其 id 为 "link"。在捕获阶段,事件监听器被附加到链接上。当你点击链接时,将显示捕获阶段的日志消息(Link clicked),并且使用 event.preventDefault()
阻止了默认行为(导航到新的页面)。
如果没有使用 preventDefault()
,将会导航到 https://www.tutorialspoint.com
。
<!DOCTYPE html>
<html>
<body>
<a href="https://www.tutorialspoint.com" id="link">Click me to prevent default</a>
<script>
document.getElementById('link').addEventListener('click', function(event) {
alert('Capturing phase - Link clicked');
event.preventDefault();
}, true);
</script>
</body>
</html>
示例:捕获和停止传播
在这个例子中,父级 div 的捕获阶段事件监听器通过使用 event.stopPropagation()
主动阻止进一步传播。只有当点击按钮时,你会看到捕获阶段的日志消息(Parent clicked)被显示出来;然而,它不会触发子元素中的任何进一步的捕获阶段动作。这确实展示了一种有效的阻止进一步传播的方法。
<!DOCTYPE html>
<html>
<body>
<div id="parent">
<button id="child">Click me!</button>
</div>
<div id = "output"></div>
<script>
const output = document.getElementById('output');
document.getElementById('parent').addEventListener('click', function(event) {
output.innerHTML += 'Capturing phase - Parent clicked' + "<br>";
event.stopPropagation();
}, true);
document.getElementById('child').addEventListener('click', function(event) {
output.innerHTML += 'Capturing phase - Child clicked' + "<br>";
}, true);
</script>
</body>
</html>