参考API地址:https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget/addEventListener#%E8%AF%AD%E6%B3%95
添加一个监听事件,首先我们看一下API的语法如下
addEventListener(type, listener);
addEventListener(type, listener, options);
addEventListener(type, listener, useCapture);
常用到的是第一个和第三个因为,useCapture默认值是false
useCapture 可选
一个布尔值,表示在 DOM 树中注册了 listener 的元素,是否要先于它下面的 EventTarget 调用该 listener。当 useCapture(设为 true)时,沿着 DOM 树向上冒泡的事件不会触发 listener。当一个元素嵌套了另一个元素,并且两个元素都对同一事件注册了一个处理函数时,所发生的事件冒泡和事件捕获是两种不同的事件传播方式。事件传播模式决定了元素以哪个顺序接收事件。进一步的解释可以查看 DOM Level 3 事件及 JavaScript 事件顺序文档。如果没有指定,useCapture 默认为 false。
这个值的作用有什么用呢?下面我开始了我的摸索和见解。废话不多说开始上demo演示。
<!DOCTYPE html>
<html lang="zh-CN>
<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>
div {
padding: 15px;
border: 1px solid #e5f3fe;
position: relative;
overflow: hidden;
}
span {
background-color: #f2f1f1;
padding: 8px 15px;
margin: 15px;
display: inline-block;
}
.description {
font-size: 22px;
font-weight: 600;
}
</style>
</head>
<body>
<p class="description">
ok 兄弟你每次点击“节点2” 就会发现这个参数的不同点了。是不是 它的触发顺序出现了不同 对 就是这样的。
</p>
<label>
<input checked onchange="radioChange(this.value)" name="useCapture" type="radio" id="radio2" value="false" />
useCapture=false
</label>
<label>
<input onchange="radioChange(this.value)" name="useCapture" type="radio" id="radio1" value="true" />
useCapture=true
</label>
<div title="节点1">
<span>节点1</span>
<div title="节点2">
<span>节点2</span>
</div>
</div>
<script>
// 个人总结:false的话 就是事件冒泡了 从子元素到父元素
// true的话 就是事件捕获 从父到子!
let useCapture = false
// 添加事件
function bindEvent() {
const targets = document.querySelectorAll('div')
targets.forEach(element => {
element.addEventListener('click', handleClick, useCapture)
});
}
// 移除事件
function removeEvent() {
const targets = document.querySelectorAll('div')
targets.forEach(element => {
element.removeEventListener('click', handleClick, useCapture)
});
}
// div click handle
function handleClick(event){
// event.stopPropagation()
alert(this.getAttribute('title'))
}
// 处理 radio change
function radioChange(checked) {
removeEvent()
console.log('radioChange')
console.log(checked)
useCapture = checked=="true" ? true : false
bindEvent()
}
// 执行绑定事件
bindEvent()
</script>
</body>
</html>
demo运行起来是这样的效果
我们发现当div或者出发事件的元素存在嵌套的情况下,这个是控制事件的执行顺序的。useCapture=false默认是冒泡,冒泡怎么理解呢就是水里的泡泡往上冒么,那么就是从子元素王父元素执行。
Capture=true就是捕获点击一下先相应父级元素的事件,然后传递到子元素。也就是先执行父的事件在执行子的事件。
还有一个就是阻止事件冒泡的 event.stopPropagation();
API文档地址:https://developer.mozilla.org/zh-CN/docs/Web/API/Event/stopPropagation
我们改动一下我们的DEMO再看看
<!DOCTYPE html>
<html lang="zh-CN>
<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>
div {
padding: 15px;
border: 1px solid #e5f3fe;
position: relative;
overflow: hidden;
}
span {
background-color: #f2f1f1;
padding: 8px 15px;
margin: 15px;
display: inline-block;
}
.description {
font-size: 22px;
font-weight: 600;
}
</style>
</head>
<body>
<p class="description">
ok 兄弟你每次点击“节点2” 就会发现这个参数的不同点了。是不是 它的触发顺序出现了不同 对 就是这样的。
</p>
<label>
<input checked onchange="radioChange(this.value)" name="useCapture" type="radio" id="radio2" value="false" />
useCapture=false
</label>
<label>
<input onchange="radioChange(this.value)" name="useCapture" type="radio" id="radio1" value="true" />
useCapture=true
</label>
<div title="节点1">
<span>节点1</span>
<div title="节点2">
<span>节点2</span>
</div>
</div>
<script>
// 个人总结:false的话 就是事件冒泡了 从子元素到父元素
// true的话 就是事件捕获 从父到子!
let useCapture = false
// 添加事件
function bindEvent() {
const targets = document.querySelectorAll('div')
targets.forEach(element => {
element.addEventListener('click', handleClick, useCapture)
});
}
// 移除事件
function removeEvent() {
const targets = document.querySelectorAll('div')
targets.forEach(element => {
element.removeEventListener('click', handleClick, useCapture)
});
}
// div click handle
function handleClick(event){
event.stopPropagation()
alert(this.getAttribute('title'))
}
// 处理 radio change
function radioChange(checked) {
removeEvent()
console.log('radioChange')
console.log(checked)
useCapture = checked=="true" ? true : false
bindEvent()
}
// 执行绑定事件
bindEvent()
</script>
</body>
</html>
发现事件触发了以后,就不再冒泡或者继续往子元素传递了。这是我的理解和简介欢迎大家拍砖。