发布于 2026-01-06 14 阅读
0

React中的事件捕获和冒泡

React中的事件捕获和冒泡

假设你有以下代码:

  const [counter, setCounter] = useState(0);
  return (
    <div onClick={() => setCounter((prevCounter) => prevCounter + 1)}>
      <button onClick={() => setCounter((prevCounter) => prevCounter + 1)}>
        Counter value is: {counter}
      </button>
    </div>
  );
Enter fullscreen mode Exit fullscreen mode

这样就渲染出了这个按钮:

屏幕截图 2020-12-10 上午 10:27:49

点击该按钮后会显示什么?

如果你猜“计数器值为:1”,那就错了

我们得到的结果是这样的:

屏幕截图 2020-12-10 上午 10:30:19

但为什么?

理解事件传播

在我们的示例中,虽然我们点击了 `<div>` 元素button,但它的父元素的事件处理程序div也被触发了。这是因为事件不仅仅影响触发事件的目标元素——它们会在 DOM 树中上下传递,最终到达目标元素。
这被称为事件传播:一种定义事件如何传播或在 DOM 树中传递以到达目标元素,以及之后会发生什么情况的机制。

事件传播的概念是为了处理DOM层级结构中多个具有父子关系的元素对同一事件(例如鼠标点击)都有事件处理程序的情况而引入的。现在的问题是,当用户点击内部元素时,哪个元素的点击事件会先被处理:是外部元素的点击事件,还是内部元素的点击事件?

事件传播分为三个阶段:

  1. 捕获阶段 - 事件从window底部开始,直到到达顶部event.target
  2. 目标阶段 - 事件已到达目标阶段event.target。引发事件的最深层嵌套元素称为目标元素,可通过以下方式访问event.target
  3. 冒泡阶段——事件从event.target元素向上冒泡,直到到达父元素window,这意味着:当一个元素上发生事件时,它首先会处理该元素的事件,然后处理其父元素的事件,再向上层处理其父元素的事件。这与捕获阶段的过程正好相反。

hjayqa99iejfhbsujlqd

React中的事件冒泡和捕获

React 对冒泡和捕获的支持方式与 DOM 规范中的描述相同,只是附加处理程序的方式有所不同。

冒泡机制与普通的 DOM API 一样简单;只需将处理程序附加到元素的最终父元素,该元素上触发的任何事件都会冒泡到父元素,就像我们开头示例中那样。

捕获操作同样简单直接,但onClick需要将属性应用onClickCapture到元素上,而不是应用到 prop 上。

如何阻止事件冒泡/捕获?

回到我们最初的例子,我们如何确保点击按钮时计数器只加 1 呢?

答案是使用stopPropagation()
此接口方法Event可以阻止当前事件在捕获和冒泡阶段的进一步传播。
但是,它不会阻止任何默认行为的发生。(如果您想阻止这些行为,则需要使用相应的preventDefault()方法。)

如果我们把代码改成:

  const [counter, setCounter] = useState(0);
  return (
    <div onClick={() => setCounter((prevCounter) => prevCounter + 1)}>
      <button
        onClick={(event) => {
          event.stopPropagation();
          setCounter((prevCounter) => {
            return prevCounter + 1;
          });
        }}
      >
        Counter value is: {counter}
      </button>
    </div>
Enter fullscreen mode Exit fullscreen mode

每次点击按钮,计数器都会加 1,这样event.stopPropagation()可以防止事件冒泡到button父级并触发父级onClick

但是,在阻止事件传播时要小心,因为有时你无法确定你不会在某个元素的父元素中需要上述事件,而这可能用于完全不同的目的。

如果情况属实,阻止传播的一种替代方法是在一个处理程序中将数据写入事件对象,并在另一个处理程序中读取它,这样就可以将有关下面处理的信息传递给父处理程序。

祝你编程愉快!🚀

文章来源:https://dev.to/eladtzemach/event-capturing-and-bubbling-in-react-2ffg