事件监听器 addEventListener
在JavaScript中,addEventListener用于向指定元素添加事件监听器。这个方法有三个参数,你是否都清楚呢?它可以更精细地控制 listener 的触发阶段。
addEventListener(type, listener, options?);
addEventListener(type, listener, useCapture?);
- type: 事件类型(如'click'、'mouseover'等)
- listener: 事件处理函数(即当事件触发时要执行的函数)
- useCapture: 可选参数,控制事件监听器是在捕获阶段还是冒泡阶段触发,默认 false 即在冒泡阶段触发
- options: 可选参数
- capture:触发时机 - true 捕获阶段;false 冒泡阶段(默认 false)
- once:设置为true,则表示 listener 会在其被调用一次后自动移除(在某些特定背景下使用,可以省去移除事件监听器的逻辑编写)
- passive: 表示listener是否永远不会调用
preventDefault()(需关注浏览器兼容性问题) - signal:该 AbortSignal 的 abort() 方法被调用时(中止请求),监听器会被移除
addEventListener 工作原理
将实现 EventListener 的函数或对象添加到调用它的 EventTarget 上的指定事件类型的事件侦听器列表中。
如果 capture 为 true,则监听器被注册为捕捉事件监听器。如果 capture 为 false,它被注册为普通事件监听器。
addEventListener() 可能被调用多次,在同一个节点上为同一种类型的事件注册多个事件句柄。但要注意,DOM 不能确定多个事件句柄被调用的顺序。
如果要绑定的函数或对象已经被添加到列表中,该函数或对象不会被再次添加。
事件流
在DOM事件模型中,事件流分为三个阶段:
捕获阶段(Capturing Phase):事件从根元素向目标元素传播目标阶段(Target Phase):事件到达目标元素冒泡阶段(Bubbling Phase):事件从目标元素向根元素传播
capture
举个例子,展示如何使用capture参数以及事件触发顺序
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>实践</title>
<style>
.container {
padding: 50px;
border: 1px solid blue;
}
.child {
padding: 50px;
border: 1px solid red;
}
</style>
</head>
<body>
<div class="container">
Container
<div class="child">Child</div>
</div>
<script>
const container = document.querySelector('.container');
const child = document.querySelector('.child');
// 捕获阶段监听container的点击事件
container.addEventListener(
'click',
function () {
console.log('Container clicked capture');
},
true,
);
// 冒泡阶段监听container的点击事件
container.addEventListener(
'click',
function () {
console.log('Container clicked bubble');
},
false,
);
// 捕获阶段监听child的点击事件
child.addEventListener(
'click',
function () {
console.log('Child clicked capture');
},
true,
);
// 冒泡阶段监听child的点击事件
child.addEventListener(
'click',
function () {
console.log('Child clicked bubble');
},
false,
);
</script>
</body>
</html>
以上代码中为 container 和 child 元素分别添加了两个点击事件监听器,一个在捕获阶段,一个在冒泡阶段,那么,点击 container 元素和点击 child 元素,分别会触发哪些事件以及触发顺序会是怎样的呢?
- 当你点击Container元素时,事件会按照以下顺序触发:
- Container clicked (capture)(捕获阶段)
- Container clicked (bubble)(冒泡阶段)
- 当你点击child元素时,事件会按照以下顺序触发:
- Container clicked (capture)(捕获阶段)
- Child clicked (capture)(捕获阶段)
- Child clicked (bubble)(冒泡阶段)
- Container clicked (bubble)(冒泡阶段)
那如果在某些特定场景下,我想点击Container元素或者点击child元素时都只触发 Container clicked (capture)事件,该如何控制?
通过这种方式,我们可以控制事件监听器是在捕获阶段还是冒泡阶段触发,从而更灵活地处理事件。