当前位置: 首页 > news >正文

React和原生事件的区别

一、核心差异对比表

维度原生事件React 事件
绑定语法HTML 属性(onclick)或 DOM API(addEventListenerJSX 中使用驼峰式属性(onClick
绑定位置直接绑定到具体 DOM 元素统一委托到根节点(React 17 及以前到 document,React 18 到容器)
事件对象原生 Event 对象,不同浏览器实现有差异合成事件 SyntheticEvent,封装原生事件并抹平浏览器差异
传播机制完整的捕获 → 目标 → 冒泡 三阶段表面只有冒泡,捕获需显式声明(如 onClickCapture),React 18 支持完整阶段
阻止传播event.stopPropagation() 阻止整个 DOM 树的传播仅阻止合成事件传播,不影响原生事件
默认行为event.preventDefault() 或 HTML 中返回 false只能使用 event.preventDefault()
this 指向默认指向 DOM 元素,可通过 bind、箭头函数修改默认 undefined,需手动绑定(构造函数、箭头函数或类属性)
触发顺序按 DOM 树层级依次触发原生事件总是先触发,合成事件在冒泡到根节点后触发
性能优化大量绑定时可能导致内存开销大事件委托 + 事件池(复用事件对象),减少监听器数量和内存占用
兼容性需处理浏览器差异(如 IE 的 attachEvent统一 API,自动处理兼容性

二、关键机制详解

1. 事件委托机制
  • 原生事件
    每个元素需单独绑定监听器,大量元素时性能较差

    // 手动为每个按钮绑定事件
    document.querySelectorAll('button').forEach(btn => {btn.addEventListener('click', handleClick);
    });
    
  • React 事件
    所有事件统一委托到根节点,通过事件类型和目标元素匹配处理函数。

    // 所有按钮的点击事件最终由根节点的统一处理器分发
    <button onClick={handleClick}>Click</button>
    
2. 合成事件 SyntheticEvent
  • 跨浏览器封装
    React 将不同浏览器的原生事件封装为统一接口,例如:

    function handleClick(e) {e.preventDefault(); // 兼容所有浏览器的阻止默认行为console.log(e.target); // 标准化的目标元素
    }
    
  • 事件池优化
    React 复用事件对象以减少 GC 压力(React 17 及以前):

    function handleClick(e) {setTimeout(() => {console.log(e.target); // React 17 及以前此处会失效,因事件对象已被重置}, 0);
    }
    
3. 事件传播差异
  • 原生事件

    预览

    <div onclick="console.log('原生冒泡')"><button onclick="console.log('原生目标')">Click</button>
    </div>
    

    传播顺序:buttondiv(冒泡阶段)。

  • React 事件

    <div onClickCapture={() => console.log('React 捕获')}><button onClick={() => console.log('React 冒泡')}>Click</button>
    </div>
    

    React 18 传播顺序:div(捕获) → button(目标) → div(冒泡)。

4. 触发顺序细节

当同时存在原生和合成事件时:

<div onClick={() => console.log('合成事件')} onMouseDown={() => console.log('合成 mousedown')}
><button onclick="console.log('原生 click')" onmousedown="console.log('原生 mousedown')">Click</button>
</div>

点击按钮的触发顺序:

  1. 原生 mousedown → 原生 click → 合成 onMouseDown → 合成 onClick

三、特殊场景对比

1. 混合使用原生与合成事件
class App extends React.Component {componentDidMount() {// 手动绑定原生事件this.buttonRef.current.addEventListener('click', () => {console.log('原生事件');});}render() {return (<button ref={this.buttonRef} onClick={() => console.log('合成事件')}>Click</button>);}
}
  • 原生事件先触发,合成事件后触发。
  • 原生事件的 stopPropagation() 会阻止合成事件触发。
2. 事件池与异步访问

React 17 及以前复用事件对象,异步访问需提前保存属性:

function handleClick(e) {const target = e.target; // 必须提前保存setTimeout(() => {console.log(target); // 正确访问console.log(e.target); // React 17 及以前会失效}, 0);
}

React 18 移除了事件池,可直接异步访问。

四、总结

特性原生事件React 事件
优势直接控制 DOM,适合复杂交互场景跨浏览器一致性,性能优化,代码简洁
劣势兼容性差,大量绑定时性能问题抽象层级高,特殊场景需结合原生事件
适用场景自定义滚动、拖拽等复杂 DOM 操作组件内交互、表单处理等常规场景

相关文章:

  • C++ 模版复习
  • LoRA:高效微调预训练模型的利器
  • 企业数字化转型的7个难点
  • t014-项目申报管理系统 【springBoot 含源码】
  • 7.atlas安装
  • 气镇阀是什么?
  • 大模型长对话中上下文无法承载全部历史,如何压缩或提取重点
  • RAG应用:交叉编码器(cross-encoder)和重排序(rerank)
  • 信息安全管理与评估2025山东卷
  • Root权限:解锁Android的终极力量
  • LLM + RAG + Vanna 综合实战
  • 移动端图片浏览插件
  • 机器视觉视觉中的棋盘格到底是什么?为什么是棋盘格?
  • python训练 60天挑战-day40
  • 在Mathematica中使用WhenEvent求解微分方程
  • 【数据库】并发控制
  • shell脚本打包成可以在麒麟桌面操作系统上使用的deb包
  • leetcode:479. 最大回文数乘积(python3解法,数学相关算法题)
  • 第十九章 正则表达式
  • 【Web应用】若依框架:基础篇12 项目结构
  • 婚纱网站设计/游戏推广公司怎么接游戏的
  • 学校手机网站模板/上海网站推广服务
  • 做网站需要什么花费/凡科建站网站
  • 受欢迎的南昌网站建设/什么是网络整合营销
  • 网站月流量5g/谷歌优化工具
  • 网站布局 种类/腾讯会议价格