參考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運作起來是這樣的效果
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>
發現事件觸發了以後,就不再冒泡或者繼續往子元素傳遞了。這是我的了解和簡介歡迎大家拍磚。