(1).事件捕获
从根元素往上传递 --- ---(由外到内)
(2).事件冒泡
从元素传递到它的根源素 --- --- (由内到外)
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<!-- js中方法需要加() 如captrueMode() -->
<body>
<div class="buttonBox">
<button class="captrue" onclick="captrueMode('捕获模式')">
捕获模式
</button>
<button class="bubbling" onclick="bubblingMode('冒泡模式')">
冒泡模式
</button>
<div>当前模式为:(<span id="activeShow"></span>)</div>
</div>
<div id="six">
6
<div id="five">
5
<div id="four">
4
<div id="three">
3
<div id="two">
2
<div id="one">1</div>
</div>
</div>
</div>
</div>
</div>
</body>
<script>
// 获取元素
const elementArr = Array.from(
document.querySelectorAll("#one, #two, #three, #four, #five, #six")
);
let modeFlag = false; // 默认 -- 冒泡模式
// 改变模式提示文字方法
const updateText = (text) => {
return (document.getElementById("activeShow").innerText = text);
};
// ! 模式效果操作函数封装
const directionHandle = function (event) {
operateHandle(event, this);
};
// 元素添加监听控制事件方法封装
const addEventIsElement = function () {
elementArr.forEach((item) =>
item.addEventListener("click", directionHandle, modeFlag)
);
};
// 元素删除监听控制事件方法封装
const removeEventIsElement = function () {
elementArr.forEach((item) =>
item.removeEventListener("click", directionHandle, modeFlag)
);
};
// 切换为捕获模式
function captrueMode(mode) {
removeEventIsElement();
(modeFlag = true), updateText(mode);
addEventIsElement();
}
// 切换为冒泡模式
function bubblingMode(mode) {
removeEventIsElement();
(modeFlag = false), updateText(mode);
addEventIsElement();
}
bubblingMode("冒泡模式"); // 默认切换为冒泡模式
let showTime = 0;
let cancelShowTime = 1000;
// !! 类名绑定操作函数 -- x
const updateClass = (thisDirection, isAccNumber = false) => {
if (isAccNumber) {
(showTime += 1000), (cancelShowTime += 1000);
}
setTimeout(() => {
thisDirection.classList.add("activeColor");
}, showTime); // 2s
setTimeout(() => {
thisDirection.classList.remove("activeColor");
}, cancelShowTime);
};
const resetTime = function () {
showTime = 0;
cancelShowTime = 1000;
};
// !! 封装操作函数 -- x
const operateHandle = (event, thisDirection) => {
if (modeFlag) {
if (thisDirection.id === "six") {
resetTime();
updateClass(thisDirection);
} else {
updateClass(thisDirection, true);
}
} else {
if (event.srcElement.id === thisDirection.id) {
resetTime();
updateClass(thisDirection);
} else {
updateClass(thisDirection, true);
}
}
};
</script>
</html>
<style lang="css">
#six {
width: 1200px;
height: 300px;
border: 1px solid #000;
text-align: center;
margin: auto;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -110%);
background-color: #fff;
}
#five {
width: 1000px;
height: 250px;
border: 1px solid #000;
margin: auto;
background-color: #fff;
}
#four {
width: 800px;
height: 200px;
border: 1px solid #000;
margin: auto;
background-color: #fff;
}
#three {
width: 600px;
height: 150px;
border: 1px solid #000;
margin: auto;
background-color: #fff;
}
#two {
width: 400px;
height: 100px;
border: 1px solid #000;
margin: auto;
background-color: #fff;
}
#one {
width: 200px;
height: 50px;
border: 1px solid #000;
margin: auto;
background-color: #fff;
}
.activeColor {
background-color: red !important;
}
.captrue {
width: 120px;
height: 36px;
}
.buttonBox {
width: 1200px;
margin: auto;
}
.bubbling {
width: 120px;
height: 36px;
}
</style>
(3). 事件委托(利用事件冒泡原理,把事件委托给父元素实现,给父元素添加点击事件,可在参数e.target中获取到点击的元素,实现此行的操作)
事件委托:在需要的时候把事件交给别的元素来做 --- ---
优点 :(1) 减少内存消耗 ---- ---- 不用在每个标签上添加事件,只需获取父元素下的元素,绑定事件即可完成全部操作。
(2) 具有动态绑定的效果 ---- ---- 在获取全部元素的条件下,不管增加或者减少的情况下都是一样的
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>JavaScript</title>
</head>
<body>
<ul id="list" style="width: 100px; margin: 0; float: left;">
<li>1<button id="rowDel">删除此条</button><button id="rowEdit">修改此条</button></li>
<li>2<button id="rowDel">删除此条</button><button id="rowEdit">修改此条</button></li>
</ul>
<button onclick="addli()">添加一个 li</button>
<script>
let list = document.getElementById("list");
function addli() {
let conentElement = document.createElement("li");
conentElement.innerHTML =
`${ list.childElementCount + 1 }<button id="rowDel">删除此条</button><button id="rowEdit">修改此条</button>`;
list.appendChild(conentElement);
};
list.onclick = function (e) {
debugger
let activeElement = e.target;
activeElement.id == "rowDel" ? list.removeChild(activeElement.parentNode) : activeElement
.parentNode.innerHTML = "<div>修改中</div>"
}
</script>
</body>
<style>
list {
display: block;
}
button {
float: right;
}
li {
width: 300px;
display: flex;
}
</style>
</html>