MST

星途 面试题库

面试题:React中事件冒泡与捕获的机制及区别

请详细阐述React中事件冒泡和捕获的工作机制,并说明两者之间的主要区别。同时,举例说明在React项目中,什么场景下你会优先使用事件冒泡,什么场景下会优先考虑事件捕获。
23.3万 热度难度
前端开发React

知识考点

AI 面试

面试题答案

一键面试

1. React中事件冒泡和捕获的工作机制

  • 事件冒泡
    • 当一个元素上的事件被触发时,该事件会从最内层的元素开始,逐渐向外层元素传播,就像气泡从水底向上浮出水面一样。例如在DOM结构中有一个 <div> 包裹着一个 <button>,当点击 <button> 时,首先 <button> 上绑定的点击事件会被触发,然后事件会依次向上传播到 <div> 以及更外层的祖先元素,只要这些祖先元素上也绑定了相同类型的点击事件,都会被依次触发。
    • 在React中,虽然合成事件的底层机制对开发者有所封装,但基本的冒泡逻辑依然存在。React会将多个不同浏览器的原生事件进行统一封装,当事件触发时,React会按照冒泡顺序依次执行绑定在不同层次组件上的事件处理函数。
  • 事件捕获
    • 事件捕获与冒泡相反,事件从最外层的祖先元素开始,向内层元素传播,直到到达实际触发事件的目标元素。还是以 <div> 包裹 <button> 为例,当点击 <button> 时,事件首先会从最外层的祖先元素开始,依次向内传播,最先触发最外层元素上绑定的事件处理函数,然后依次向内层元素传播,直到到达 <button>
    • 在React中,可以通过在 addEventListener 的第三个参数设置为 true 来开启事件捕获,不过在React的合成事件系统中,通过 useEffect 等方式模拟原生事件捕获时需要注意其与合成事件机制的结合使用。

2. 两者之间的主要区别

  • 传播方向:事件冒泡是从目标元素向祖先元素传播;事件捕获是从祖先元素向目标元素传播。
  • 执行顺序:在事件流的处理过程中,事件捕获阶段先于目标阶段,而目标阶段之后是事件冒泡阶段。在React合成事件中,如果同时存在捕获和冒泡的事件处理函数,捕获阶段的函数会先执行,然后才是目标元素上的事件处理函数,最后是冒泡阶段的函数。
  • 默认绑定方式:在React中,合成事件默认使用事件冒泡机制,这样可以在父组件中方便地统一处理子组件的事件,而无需为每个子组件都单独绑定事件处理函数。

3. 场景举例

  • 优先使用事件冒泡的场景
    • 表单验证:例如有一个包含多个输入框的表单,每个输入框都有自己的输入验证逻辑。同时,表单还有一个提交按钮,当点击提交按钮时,需要验证所有输入框是否都满足要求。可以在每个输入框上绑定 onChange 事件,并在父表单组件上也绑定一个 onChange 事件。当输入框内容改变时,事件冒泡到表单组件,表单组件可以统一收集所有输入框的状态并进行整体验证。这样可以避免为每个输入框都单独编写提交验证的逻辑,使代码更加简洁和易于维护。
    • 菜单点击处理:假设有一个多级菜单结构,每个菜单项都有点击事件。当点击某个菜单项时,除了执行该菜单项自身的逻辑外,可能还需要在父菜单级别进行一些状态更新,比如记录当前选中的菜单项层级等。通过事件冒泡,可以在父菜单组件中统一处理这些逻辑,而不需要为每个菜单项都单独绑定到顶层的处理函数。
  • 优先考虑事件捕获的场景
    • 页面点击遮罩层关闭:例如在一个弹出框组件中,弹出框有一个遮罩层,当点击遮罩层时需要关闭弹出框。同时,弹出框内部可能还有一些按钮等交互元素。如果使用事件冒泡,当点击弹出框内部按钮时,事件也会冒泡到遮罩层,导致弹出框意外关闭。此时使用事件捕获,在遮罩层上绑定点击事件捕获,只有当点击事件从外层向内传播到遮罩层时才会触发关闭逻辑,这样可以避免内部元素点击误触发遮罩层的关闭事件。
    • 安全控制区域:假设页面中有一个安全控制区域,只有当用户在该区域内触发事件时才进行特定的权限验证等操作。可以在该区域的外层元素上绑定事件捕获,当事件从外层向内传播到该区域时,首先进行权限验证等操作,确保只有有权限的用户操作才会继续向内传播到实际的目标元素,从而提高安全性。