一、事件冒泡和事件捕获
让我们先从一个例子开始:
<div onclick="alert('div')">DIV
<p onclick="alert('p')">P</p>
</div>
我们在p元素和div元素都添加点击事件的处理程序,然后点击p元素,会发现上div的处理程序也会运行。
事件冒泡
原理:当一个事件发生在一个元素上,它会首先运行在该元素上的处理程序,然后运行其父元素上的处理程序,然后一直向上到其他祖先上的处理程序。事件从目标元素“冒泡”到所有父级元素,这个过程就像水里的气泡一样。
p -> div -> body -> html ->document
事件捕获
与事件冒泡相反,事件从最外层的元素发生,直到目标元素。
document ->html -> body -> div -> p
事件冒泡和事件捕获的过程图:
先捕获后冒泡。1-5是捕获过程,5-6是目标阶段,6-10是冒泡过程。
二、addEventListener 的第三个参数
addEventListener方法用来为一个特定的元素绑定一个时间处理函数,是JavaScript中常用的方法。
该方法的第三个参数指定事件是否在捕获或冒泡阶段执行。
elem.addEventListener(...,{capture: true})
// 或者,用{capture: true} 的别名 “true”
elem.addEventListener(...,true)
capture选项有两个可能的值:
- 如果为 false (默认值),则在冒泡阶段设置处理程序。
- 如果true,则在捕获阶段设置处理程序。
event.target
父元素上的处理程序始终可以获取事件实际发生位置的详细信息。
通过event.target可以访问到目标元素。
注意与this (= event.currentTarget ) 之间的区别:
- event.target —— 是引发事件的"目标"元素,它在冒泡过程中不会发生变化。
- this —— 是“当前”元素,其中有一个当前正在运行的处理程序。
阻止事件冒泡
1. 给子级加event.stopPropagation()
elem.addEventListener('click',(event)=>{
event.stopPropagation();
})
2. 在事件处理函数中返回false
elem.addEventListener('click',(event)=>{
const e = event || window.event;
return false;
})
但是这两种方式是有区别的。return false 不仅阻止了事件往上冒泡,而且阻止了事件本身(默认事件)。event.stopPropagation()则只阻止事件往上冒泡,不阻止事件本身。
三、有什么作用
- 事件冒泡允许多个操作被集中处理(把事件处理器添加到一个父级元素上,避免把事件处理器添加到多个子级元素上),它还可以让你在对象层的不同级别捕获事件。
- 让不同的对象同时捕获同一事件,并调用自己的专属处理程序做自己的事情,就像老板一下命令,各自员工做自己岗位上的工作去了。