跳到主要内容

事件✅

事件冒泡是什么?

答案

参考 w3c ui event 冒泡机制是为了解决在如何在 DOM 树上广播事件。整个广播流程参考下图:

整个事件从创建到完成的流程如下

  1. 事件产生,用户点击等操作,此时会创建一个 event target 对象包含出发事件时的相关信息
    • target 指向触发事件的元素
    • currentTarget 只读属性指向事件分发过程中的当前对象
    • 在回调函数中 this 指向 currentTarget.
  2. 根据当前触发元素确定传播路径
  3. 事件分发,此时时间会在 DOM 树上进行广播,广播分为三个阶段
    1. 捕获阶段 从传播路径的根元素向目标元素传播,从 window 开始
    2. 目标阶段 当传播到达事件目标时
    3. 冒泡阶段 当从事件目标对象向父元素广播时从 window 结束。

事件广播过程会修改 event target 相关状态,此外可以利用 stopPropagation 对事件传播进行截断。

  1. 事件处理阶段,在事件分发过程中若传播路径有元素绑定了回调事件,event target 对象作为传入参数触发执行。

参考 w3c ui event 说明

但目标元素触发事件时,事件的分发分为三个阶段:

  1. 捕获阶段(capture phase) 从根元素逐级向目标元素传递
  2. 目标阶段(target phase) 传递到目标元素的阶段
  3. 冒泡阶段(bubbling phase) 从目标元素重新传递到根元素的阶段

事件委托的作用和意义?

答案

事件委托是一种常用的事件处理模式,主要通过将事件监听器添加到父元素上,而不是每个子元素上,从而提高性能和简化代码。其作用和意义包括:

  1. 提高性能:减少事件监听器的数量,降低内存消耗,尤其在子元素较多时更为明显。
  2. 简化代码:通过事件冒泡,父元素可以处理所有子元素的事件,避免为每个子元素单独绑定事件。
  3. 动态添加元素:对于动态生成的子元素,父元素的事件监听器可以自动响应,无需重新绑定事件。

说明 load,ready,DOMContentLoaded 的区别

答案
属性DOMContentLoadedloadready
触发时机DOM结构解析完成页面所有资源加载完毕DOM结构解析完成
典型用途尽早操作DOM、初始化交互依赖全部资源的操作早期DOM操作、兼容性处理
是否等待外部资源
适用范围原生JS原生JSjQuery专用
// 原生 DOMContentLoaded
document.addEventListener('DOMContentLoaded', () => {
// DOM 可操作
})

// 原生 load
window.addEventListener('load', () => {
// 所有资源加载完毕
})

// jQuery ready
$(function () {
// DOM 可操作
})
提示

推荐优先使用 DOMContentLoaded 或 jQuery 的 ready,可提升页面响应速度和用户体验。

注意

load 事件需等待所有资源加载,页面大图或慢资源会延迟触发,影响初始化时机。

延伸阅读

stopImmediatePropagation 和 stopPropagation 区别

答案

stopPropagationstopImmediatePropagation 都用于阻止事件冒泡,但作用范围不同:

|方法|作用范围|典型场景| |event.stopPropagation()|阻止事件继续向父元素冒泡,但同一元素上后续监听器仍会执行|只需阻止冒泡,不影响本元素其他事件处理| |event.stopImmediatePropagation()|阻止事件冒泡,并阻止当前元素上后续所有同类型事件监听器执行|彻底阻断冒泡和本元素后续处理|

const btn = document.getElementById('btn')
btn.addEventListener('click', () => { console.log('handler1') })
btn.addEventListener('click', (e) => {
e.stopImmediatePropagation()
console.log('handler2')
})
btn.addEventListener('click', () => { console.log('handler3') })

/*
点击 btn 时,只输出 handler2,handler1/handler3 都不会执行
*/

如果用 stopPropagation(),则 handler1、handler2 都会执行,handler3 不会因冒泡被阻止。

  • stopPropagation 只影响冒泡,不影响同一元素的其他监听器。
  • stopImmediatePropagation 更彻底,常用于防止重复触发或冲突处理。
提示

如需彻底阻止事件在当前元素的所有后续处理,优先用 stopImmediatePropagation

延伸阅读

addEventListener 和 attribute onclick

答案

addEventListener 绑定事件?参数不同的执行顺序

mouseEnter、mouseLeave、mouseOver、mouseOut 有什么区别?

答案

下表总结了四个鼠标事件的主要区别:

事件名触发时机是否冒泡子元素影响典型用途
mouseenter鼠标进入元素本身只需关注本元素的进入
mouseleave鼠标离开元素本身只需关注本元素的离开
mouseover鼠标进入元素或其子元素需监控元素及子元素的进入
mouseout鼠标离开元素或其子元素需监控元素及子元素的离开
element.addEventListener('mouseenter', () => console.log('mouseenter'))
element.addEventListener('mouseleave', () => console.log('mouseleave'))
element.addEventListener('mouseover', () => console.log('mouseover'))
element.addEventListener('mouseout', () => console.log('mouseout'))
提示

有嵌套子元素时,推荐用 mouseenter/mouseleave,可避免鼠标在父子元素间频繁触发事件。

备注

mouseover/mouseout 适合需要对子元素进入/离开也做处理的场景,如复杂菜单。

延伸阅读

55%