1. dom 事件流
DOM结构是一个树型结构,当一个 HTML元素 产生一个事件时,该事件会在元素节点与根结点之间的路径传播,路径所经过的结点都会收到该事件,这个传播过程可称为DOM事件流。
当触发事件时,该事件的捕获阶段最先开始,从 Document 节点开始逐渐向下传播,直到触发源事件进入目标阶段,在目标阶段结束之后,事件由触发源开始事件的冒泡阶段,直到 Document 节点为止,即3个阶段:
- 捕获阶段
- 目标阶段
- 冒泡阶段
2. 冒泡与捕获演示
使用 addEventListener 注册事件
event | 指定事件名,不要使用 "on" 前缀,可以完整的 HTML DOM Event 对象参考手册 |
---|---|
function | 必须,指定要事件触发时执行的函数,当事件对象会作为第一个参数传入函数 |
useCapture |object | 可选。布尔值或对象,指定事件是否在捕获或冒泡阶段执行,可能值: true - 事件句柄在捕获阶段执行;false- 默认。事件句柄在冒泡阶段执行 |
分三种场景做演示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>冒泡与捕获</title>
<style>
#b1 {
width: 100px;
}
div {
padding: 20px;
border: 1px solid red;
}
</style>
</head>
<body>
<div id="b1">
<div id="b2">
<div id="b3"></div>
</div>
</div>
</body>
<script>
var b1 = document.querySelector("#b1");
var b2 = document.querySelector("#b2");
var b3 = document.querySelector("#b3");
// 1. 全是冒泡阶段执行,谁的层级深,谁的回调先执行 => b3 b2 b1
// b1.addEventListener('click', function() {
// console.log("b1 click")
// })
// b2.addEventListener('click', function() {
// console.log("b2 click")
// })
// b3.addEventListener('click', function() {
// console.log("b3 click")
// })
// 2. 全是捕获阶段执行,谁的层级低,谁的回调先执行 => b1 b2 b3
// b1.addEventListener('click', function() {
// console.log("b1 click")
// }, true)
// b2.addEventListener('click', function() {
// console.log("b2 click")
// }, true)
// b3.addEventListener('click', function() {
// console.log("b3 click")
// }, true)
// 3. 混合,先执行捕获, 再冒泡 => b2 b3 b1
b1.addEventListener('click', function() {
console.log("b1 click")
})
b2.addEventListener('click', function() {
console.log("b2 click")
}, true)
b3.addEventListener('click', function() {
console.log("b3 click")
})
</script>
</html>
3. 阻止事件的传播
如下代码分别演示了,在冒泡阶段阻止事件传播,以及在捕获阶段阻止事件传播:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#b1 {
width: 100px;
}
div {
padding: 20px;
border: 1px solid red;
}
</style>
</head>
<body>
<div id="b1">
<div id="b2">
<div id="b3"></div>
</div>
</div>
</body>
<script>
var b1 = document.querySelector("#b1");
var b2 = document.querySelector("#b2");
var b3 = document.querySelector("#b3");
// 1. => b3 b2
// b1.addEventListener('click', function() {
// console.log("b1 click")
// })
// b2.addEventListener('click', function(e) {
// console.log("b2 click")
// e.stopPropagation(); // b1 冒泡回调不会执行
// })
// b3.addEventListener('click', function() {
// console.log("b3 click")
// })
// 2. => b1 true click
b1.addEventListener('click', function(e) {
console.log("b1 true click")
e.stopPropagation(); // 由于是在捕获阶段就阻止了事件传播,所以其子元素都不会触发事件
}, true)
b1.addEventListener('click', function(e) {
console.log("b1 false click")
}, false)
b2.addEventListener('click', function() {
console.log("b2 click")
}, true)
b2.addEventListener('click', function() {
console.log("b2 false click")
}, false)
b3.addEventListener('click', function() {
console.log("b3 click")
}, true)
</script>
</html>
网友评论