由此可以知道
1、一个完整的JS事件流是从window开始,最后回到window的一个过程
2、事件流被分为三个阶段(15)捕获过程、(56)目标过程、(6~10)冒泡过程
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
#wrapDiv,
#innerP,
#textSpan {
margin: 5px;
padding: 5px;
box-sizing: border-box;
cursor: default;
}
#wrapDiv {
width: 300px;
height: 300px;
border: indianred 3px solid;
}
#innerP {
width: 200px;
height: 200px;
border: hotpink 3px solid;
}
#textSpan {
display: block;
width: 100px;
height: 100px;
border: orange 3px solid;
}
</style>
</head>
<body>
<div id="wrapDiv">wrapDiv
<p id="innerP">innerP
<span id="textSpan">textSpan</span>
</p>
</div>
<script>
test_01 = () => {
var wrapDiv = document.getElementById("wrapDiv");
var innerP = document.getElementById("innerP");
var textSpan = document.getElementById("textSpan");
// 捕获阶段绑定事件
window.addEventListener("click", function (e) {
console.log("window 捕获", e.target.nodeName, e.currentTarget.nodeName);
}, true);
document.addEventListener("click", function (e) {
console.log("document 捕获", e.target.nodeName, e.currentTarget.nodeName);
}, true);
document.documentElement.addEventListener("click", function (e) {
console.log("documentElement 捕获", e.target.nodeName, e.currentTarget.nodeName);
}, true);
document.body.addEventListener("click", function (e) {
console.log("body 捕获", e.target.nodeName, e.currentTarget.nodeName);
}, true);
wrapDiv.addEventListener("click", function (e) {
console.log("wrapDiv 捕获", e.target.nodeName, e.currentTarget.nodeName);
}, true);
innerP.addEventListener("click", function (e) {
console.log("innerP 捕获", e.target.nodeName, e.currentTarget.nodeName);
}, true);
textSpan.addEventListener("click", function (e) {
console.log("textSpan 捕获", e.target.nodeName, e.currentTarget.nodeName);
}, true);
// 冒泡阶段绑定的事件
window.addEventListener("click", function (e) {
console.log("window 冒泡", e.target.nodeName, e.currentTarget.nodeName);
}, false);
document.addEventListener("click", function (e) {
console.log("document 冒泡", e.target.nodeName, e.currentTarget.nodeName);
}, false);
document.documentElement.addEventListener("click", function (e) {
console.log("documentElement 冒泡", e.target.nodeName, e.currentTarget.nodeName);
}, false);
document.body.addEventListener("click", function (e) {
console.log("body 冒泡", e.target.nodeName, e.currentTarget.nodeName);
}, false);
wrapDiv.addEventListener("click", function (e) {
console.log("wrapDiv 冒泡", e.target.nodeName, e.currentTarget.nodeName);
}, false);
innerP.addEventListener("click", function (e) {
console.log("innerP 冒泡", e.target.nodeName, e.currentTarget.nodeName);
}, false);
textSpan.addEventListener("click", function (e) {
console.log("textSpan 冒泡", e.target.nodeName, e.currentTarget.nodeName);
}, false);
}
// test_01();
test_02 = () => {
var wrapDiv = document.getElementById("wrapDiv");
var innerP = document.getElementById("innerP");
var textSpan = document.getElementById("textSpan");
// 测试直接绑定的事件到底发生在哪个阶段
wrapDiv.onclick = function () { //作用于非目标的事件,会遵守先捕获后冒泡的规则执行。且绑定的事件会在冒泡阶段执行,对比于冒泡事件,谁在前谁先执行。
console.log("wrapDiv onclick 测试直接绑定的事件到底发生在哪个阶段")
};
wrapDiv.addEventListener("click", function (e) {
console.log("wrapDiv 冒泡", e.target.nodeName, e.currentTarget.nodeName);
}, false);
// 捕获阶段绑定事件
window.addEventListener("click", function (e) {
console.log("window 捕获", e.target.nodeName, e.currentTarget.nodeName);
}, true);
document.addEventListener("click", function (e) {
console.log("document 捕获", e.target.nodeName, e.currentTarget.nodeName);
}, true);
document.documentElement.addEventListener("click", function (e) {
console.log("documentElement 捕获", e.target.nodeName, e.currentTarget.nodeName);
}, true);
document.body.addEventListener("click", function (e) {
console.log("body 捕获", e.target.nodeName, e.currentTarget.nodeName);
}, true);
wrapDiv.addEventListener("click", function (e) {
console.log("wrapDiv 捕获", e.target.nodeName, e.currentTarget.nodeName);
}, true);
innerP.addEventListener("click", function (e) {
console.log("innerP 捕获", e.target.nodeName, e.currentTarget.nodeName);
}, true);
textSpan.onclick = function () { //作用于目标的事件,不会遵守先捕获后冒泡的规则执行。该目标绑定的事件和冒泡事件,都会在该目标的捕获事件之前执行。且绑定的事件和冒泡事件,谁在前谁先执行。
console.log("textSpan onclick")
};
textSpan.addEventListener("click", function () {
console.log("textSpan 冒泡 在捕获之前绑定的")
}, false);
textSpan.addEventListener("click", function (e) {
console.log("textSpan 捕获", e.target.nodeName, e.currentTarget.nodeName);
}, true);
// 冒泡阶段绑定的事件
window.addEventListener("click", function (e) {
console.log("window 冒泡", e.target.nodeName, e.currentTarget.nodeName);
}, false);
document.addEventListener("click", function (e) {
console.log("document 冒泡", e.target.nodeName, e.currentTarget.nodeName);
}, false);
document.documentElement.addEventListener("click", function (e) {
console.log("documentElement 冒泡", e.target.nodeName, e.currentTarget.nodeName);
}, false);
document.body.addEventListener("click", function (e) {
console.log("body 冒泡", e.target.nodeName, e.currentTarget.nodeName);
}, false);
innerP.addEventListener("click", function (e) {
console.log("innerP 冒泡", e.target.nodeName, e.currentTarget.nodeName);
}, false);
textSpan.addEventListener("click", function (e) {
console.log("textSpan 冒泡", e.target.nodeName, e.currentTarget.nodeName);
}, false);
}
test_02();
</script>
</body>
</html>
直接说结论:
作用于非目标的事件,会遵守先捕获后冒泡的规则执行。且绑定的事件会在冒泡阶段执行,对比于冒泡事件,谁在前谁先执行。
作用于目标的事件,不会遵守先捕获后冒泡的规则执行。该目标绑定的事件和冒泡事件,都会在该目标的捕获事件之前执行。且绑定的事件和冒泡事件,谁在前谁先执行。
来源 chenxj :https://www.cnblogs.com/Chen-XiaoJun/p/6210987.html