事件冒泡(Event Bubbling)
事件冒泡是事件流的一个阶段,事件最初在目标元素上触发,然后逐层向上传播到其父级元素,直到到达最顶层的document
或 window
。冒泡机制允许父级元素在事件向上传播时捕获并处理该事件。
事件冒泡是事件流执行的默认顺序。
简而言之,事件冒泡指的是从里到外逐层传递,先触发子元素,再逐步传递给父元素。
<body>
<div class="square red">
<div class="square blue">
<div class="square green"></div>
</div>
</div>
</body>
</html>
<script>
document.querySelector('.red').addEventListener('click', function(event) {
{
alert('红色区域被点击了');
}
});
document.querySelector('.blue').addEventListener('click', function(event) {
{
alert('蓝色区域被点击了');
}
});
document.querySelector('.green').addEventListener('click', function(event) {
alert('绿色区域被点击了');
});
</script>
像这样,当我们点击位于最内部的“绿色”,弹出顺序是由内向外的绿、蓝、红。
事件捕获(Event Capturing)
事件捕获是事件流的另一个阶段,事件首先从最顶层的祖先元素(如document
)开始向下传播,直到到达目标元素。在捕获阶段,父级元素可以在事件到达目标之前处理事件。事件捕获是事件冒泡的相反方向,较少使用,但可以通过设置监听器选项来指定事件在捕获阶段触发。
简而言之,事件捕获是从外到里逐层传递,先触发父元素,再逐步传递给子元素。
<script>
document.querySelector('.red').addEventListener('click', function(event) {
{
alert('红色区域被点击了');
}
},true);
document.querySelector('.blue').addEventListener('click', function(event) {
{
alert('蓝色区域被点击了');
}
},true);
document.querySelector('.green').addEventListener('click', function(event) {
alert('绿色区域被点击了');
},true);
</script>
在这里,我们将addEventListener
事件的第三个参数改为了true
(因为其默认是False
,即默认执行的是事件冒泡),由此我们将这一事件流的执行改为了事件捕获。当我们点击最内侧的“绿色”,弹出的顺序是由外向内的红、蓝、绿。
那我们如何实现点击绿色只弹出绿色的操作呢?
这里的修改主要有以下几点:
-
将所有事件监听器的第三个参数
true
改为false
,这样使用事件冒泡而不是事件捕获。 -
在绿色区域的事件处理函数中,添加了
event.stopPropagation()
,这会阻止事件继续冒泡到父元素。 -
对于红色和蓝色区域,添加了条件判断
if (event.target.classList.contains('...'))
,这确保只有当点击的是相应颜色的区域时才会触发 alert。
<script>
document.querySelector('.red').addEventListener('click', function(event) {
if (event.target.classList.contains('red')) {
alert('红色区域被点击了');
}
},true);
document.querySelector('.blue').addEventListener('click', function(event) {
if (event.target.classList.contains('blue')) {
alert('蓝色区域被点击了');
}
},true);
document.querySelector('.green').addEventListener('click', function(event) {
alert('绿色区域被点击了');
},true);
</script>
这样修改后,点击绿色区域只会弹出"绿色区域被点击了",而不会触发蓝色和红色区域的事件。点击蓝色区域会弹出"蓝色区域被点击了",点击红色区域(不包括蓝色和绿色部分)会弹出"红色区域被点击了"。