前言:js里面事件就是指用户执行某些行为(本文以点击行为为例)后,浏览器会发出相应的事件响应,而用户可以捕获这些事件,并在其中写相应的逻辑代码。本文详细介绍浏览器对事件的传播机制(事件冒泡、事件捕获),以及事件委托(代理)一种代码设计模式。
一、事件冒泡
嵌套的DOM结果,如果点击子元素,会触发父元素的点击行为
<body>
<div id="outside">
outside
<div id="center">
center
<div id="inside">inside</div>
</div>
</div>
<script>
const inside = document.getElementById("inside");
const center = document.getElementById("center");
const outside = document.getElementById("outside");
inside.addEventListener("click", () => {
console.log("inside");
});
center.addEventListener("click", () => {
console.log("center");
});
outside.addEventListener("click", () => {
console.log("outside");
});
</script>
</body>
如果点击inside区域,会出现如下效果,这就是事件冒泡
停止冒泡
如果需要停止上述冒泡行为,可以将处理函数修改如下
inside.addEventListener("click", (e) => {
e.stopPropagation();
console.log("inside");
});
二、事件捕获
浏览器对事件响应的整个阶段如下(window -> document省略,只从DOM树分析)
事件冒泡阶段只是浏览器对事件响应整个阶段的后半部分,前面还有事件捕获阶段,这阶段的代码修改为如下:
inside.addEventListener(
"click",
(e) => {
console.log("inside");
},
true
);
或者
inside.addEventListener(
"click",
(e) => {
console.log("inside");
},
{ capture: true }
);
三、事件委托/代理
事件委托可以理解称一种代码设计模式,比如上述例子三个DOM分别注册了点击事件,如果嵌套(或者扁平化)了更多的DOM,一个个注册事件在代码逻辑上较为重复且在性能会有所损耗(绑定事件越多,浏览器内存占用越大)。事件委托则是利用事件捕获机制,在这些DOM的一个父元素上只注册一个点击事件即可,上述例子利用事件委托可以写成
<body>
<div id="outside">
outside
<div id="center">
center
<div id="inside">inside</div>
</div>
</div>
<script>
document.querySelector("body").addEventListener("click", (e) => {
console.log(e.target.id);
});
</script>
</body>
❗实际代码不要用body作为父元素
哥们也做一回标题党
评论区