【react】合成事件

27 阅读2分钟

react合成事件

React 合成事件是 React 自己实现的一套事件系统,它是对浏览器原生事件 (Native Event) 的一层封装

为什么react要自己在封装原生的事件系统呢?

解决浏览器兼容性问题

不同浏览器对事件的实现存在差异。例如:

  • 获取事件目标:IE 中是 event.srcElement,而标准浏览器是 event.target。
  • 阻止事件冒泡:IE 中是 event.cancelBubble = true,而标准浏览器是 event.stopPropagation()。

提升性能和管理效率

在传统的 Web 开发中,如果页面上有大量的元素需要绑定事件(比如一个巨大的列表),为每个 DOM 元素都添加一个事件监听器会占用大量内存,并可能影响性能。

React 采用了一种更高效的模式:事件委托 (Event Delegation)

特性传统方式 (为每个 item 绑定)React 方式 (事件委托)
真实监听器数量1000 个1 个 (针对 click 事件)
监听器位置每个 
  •  元素上
  • 应用的根节点上
    内存占用极低
    初始性能较慢 (需要执行 1000 次绑定)极快 (只需执行 1 次绑定)
    动态内容管理复杂 (需要手动为新增元素绑定/解绑)自动 (新增的 li 无需任何操作,点击时事件依然能被根节点捕获并正确处理)

    react阻止事件传递的原理

    function App() {
    const handleParentClick = () => {
      console.log('Parent Div clicked');
    };
    
    const handleChildClick = (e) => {
      console.log('Child Button clicked');
      // 我们在这里调用 stopPropagation
      e.stopPropagation(); 
    };
    
    return (
      <div onClick={handleParentClick} style={{ padding: '20px', border: '1px solid red' }}>
        <button onClick={handleChildClick}>Click Me</button>
      </div>
    );
    }
    

    当你点击 "Click Me" 按钮时,会发生以下事情:

    1. **原生冒泡 (不受影响)** :浏览器的原生 click 事件从  触发,然后冒泡到 

      ,再到 ,最后到应用的根节点。这个过程没有被阻止

    2. React 监听到事件:在根节点,React 的监听器被触发。它检查原生事件的 target,发现是那个 。

    3. React 开始分发:React 开始了它的“模拟冒泡”之旅。

      • 第一站:按钮组件。React 找到了与  对应的 onClick 处理器,也就是 handleChildClick。

      • 执行 handleChildClick

        • console.log('Child Button clicked'); 被执行,你在控制台看到了 "Child Button clicked"。
        • e.stopPropagation() 被调用。
    4. stopPropagation 的魔法:当 e.stopPropagation() 被调用时,React 会在这个合成事件对象 e 上设置一个内部标志,比如 isPropagationStopped = true。

    5. React 停止分发

      • handleChildClick 执行完毕后,React 的分发器准备继续向上“冒泡”到父级 
      • 在调用 handleParentClick 之前,分发器会检查合成事件对象 e 上的 isPropagationStopped 标志。
      • 它发现这个标志是 true!
      • 因此,React 决定不再继续向上分发事件。handleParentClick 函数永远不会被调用