总览
处理顺序:事件捕获
-> 事件处理
-> 事件冒泡
addEventListener
我们通过浏览器的addEventListener
方法可以为Element
、Document
、Window
添加事件监听器。当指定事件发生时,触发回调函数。
它比onxxx
添加事件回调函数好的一点,是可以同时添加多个事件回调函数。
addEventListener 支持三种使用方式:
addEventListener(type, listener);
addEventListener(type, listener, options);
addEventListener(type, listener, useCapture);
type
事件类型,例如: click、mousedowm(对应onclick、onmousedown)。listener
事件监听回调函数,事件处理相关的逻辑。- 当第三个参数是布尔类型值(即
useCapture
)时,如果是 true,触发捕获回调。默认是false,触发冒泡回调。 - 当第三个参数是对象时,会查找这几个属性:
capture
、once
、passive
、signal
。
capture: 表示捕获阶段时触发,等价于第三个参数值为true。 默认false。
once:只调用一次,调用后自动移除。默认false
passive:永远不会调用e.preventDefault()。默认false
signal:传入一个AbortSignal,执行abort()方法会移除监听器。
事件捕获
事件从最外层依次向内执行,直到到目标元素。
捕获示例:window.addEventListener('click', e => {}, true)
或window.addEventListener('click', e => {}, {capture: true})
事件冒泡
事件从目标元素向外执行,直到最外层。
冒泡示例:window.addEventListener('click', e => {})
事件委托
在外层拦截子元素的事件做集中管理。
1.解决了什么问题
事件委托是为了解决大量添加重复事件监听器的行为,导致消耗大量资源的问题。
假设一个下拉框组件,内部有1000个Item,每个Item都添加一个若干监听事件,无疑会造成大量的内存消耗和浪费。
我们可以只在下拉框组件包裹Item组件的div标签统一监听各种事件,通过比对 e.target
判断当前操作的元素,来进行精细的操作。
2.注意问题
由于通过addEventListener
方式来做统一事件监听与拦截,如果子元素与包裹容器之间,有某层元素使用stopPropagation
阻止了事件冒泡,事件委托便会发生遗漏。
因此,使用时最好紧邻监听的子元素。
演示
我用简单的两张图片展示捕获、冒泡的顺序方向。
原文链接:https://juejin.cn/post/7221085314483634234 作者:风与夜