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

React中的stopPropagation和preventDefault

事件冒泡、捕获是DOM事件传播的核心机制,而stopPropagationpreventDefault是控制事件行为的关键方法。React的合成事件体系基于原生事件封装,但在表现上有显著差异。下面分三部分详细说明:

一、事件冒泡与捕获的区别

DOM事件传播遵循“事件流”模型,分为三个阶段(从外到内再到外),其中“捕获”和“冒泡”是核心阶段:

阶段传播方向触发顺序作用
捕获阶段从顶层元素(window)向目标元素传播先执行由外向内“捕获”事件,让上层元素有机会在事件到达目标前处理(如全局拦截)。
目标阶段事件到达实际触发的元素(目标元素)中间执行目标元素的事件处理函数触发。
冒泡阶段从目标元素向顶层元素(window)传播后执行由内向外“冒泡”事件,让上层元素有机会在事件离开目标后处理(如事件委托)。

示例

<div id="grandparent"><div id="parent"><button id="child">点击</button></div>
</div>

点击child按钮时,事件流顺序为:

  1. 捕获阶段window → document → grandparent → parent → child(从外到内);
  2. 目标阶段child(事件到达目标);
  3. 冒泡阶段child → parent → grandparent → document → window(从内到外)。

核心区别

  • 传播方向相反:捕获是“自上而下”,冒泡是“自下而上”;
  • 触发时机不同:捕获阶段的事件处理函数先于冒泡阶段执行(若同时绑定)。

二、stopPropagationpreventDefault的作用

两者都是事件对象(event)的方法,但作用完全不同:

1. event.stopPropagation()
  • 作用:阻止事件继续在事件流中传播(包括捕获和冒泡阶段)。
  • 效果:事件到达当前元素后,不会再向其他元素传播(无论是上层还是下层)。

示例
parent在冒泡阶段绑定事件,且child的事件处理中调用stopPropagation(),则点击child时,parentgrandparent的冒泡事件不会触发。

2. event.preventDefault()
  • 作用:阻止事件的“默认行为”(浏览器为某些事件预设的行为)。
  • 不影响:事件的传播(捕获和冒泡会正常进行)。

常见默认行为

  • <a>标签点击跳转;
  • <form>表单提交后刷新页面;
  • 右键点击弹出上下文菜单。

示例
<a href="https://example.com" onclick="event.preventDefault()">链接</a>
点击链接时,不会跳转(默认行为被阻止),但事件仍会正常冒泡到父元素。

三、React合成事件体系下的表现

React的“合成事件”(SyntheticEvent)是对原生DOM事件的封装,目的是统一跨浏览器的事件行为,并通过“事件委托”优化性能。其表现与原生事件有以下核心差异:

1. 事件委托机制

React不会将事件直接绑定到DOM元素上,而是将所有事件委托到根节点(React 17前是document,17后是挂载的根节点,如#root)。当事件触发并冒泡到根节点时,React再根据事件源分发到对应的组件处理函数。

2. 捕获阶段的处理方式
  • 原生事件:通过addEventListener(event, handler, true)的第三个参数true绑定捕获阶段的处理函数。
  • React合成事件:默认在冒泡阶段处理事件;若需在捕获阶段处理,需在事件名后加Capture后缀(如onClickCapture而非onClick)。

示例

// 父组件在捕获阶段处理事件
<div onClickCapture={() => console.log('父元素捕获')}><button onClick={() => console.log('子元素冒泡')}>点击</button>
</div>
// 点击按钮时,输出顺序:父元素捕获 → 子元素冒泡(符合捕获先于冒泡的规则)
3. stopPropagation()的差异
  • 原生事件:调用后会阻止事件在整个DOM树中的传播(包括到达React的委托根节点)。
  • React合成事件:调用e.stopPropagation()只能阻止合成事件的传播(即其他React组件的事件处理函数不会触发),但无法阻止原生事件的传播(因为原生事件已经冒泡到了根节点,React只是在此时分发合成事件)。

反例

// 子组件(合成事件)
<button onClick={(e) => {e.stopPropagation(); // 阻止合成事件传播console.log('子元素合成事件');}}// 原生事件ref={(el) => {el?.addEventListener('click', () => console.log('子元素原生事件'));}}
>点击
</button>// 父组件(合成事件)
<div onClick={() => console.log('父元素合成事件')}>{/* 子组件 */}
</div>

点击按钮时:

  • 子元素的合成事件和原生事件都会触发;
  • 父元素的合成事件不会触发(因为合成事件的传播被阻止);
  • 若父元素同时绑定了原生事件(如addEventListener),则会触发(因为原生事件的传播未被阻止)。
4. preventDefault()的差异
  • 作用与原生一致:阻止事件的默认行为(如表单提交、链接跳转)。
  • 注意点:React中不能通过return false同时实现阻止默认行为和传播(与原生DOM不同)。原生中return false等价于同时调用preventDefault()stopPropagation(),但React中return false无效,必须显式调用对应方法。
5. 事件池机制(React 17前)

React 17之前,合成事件对象会被放入“事件池”复用(性能优化),事件处理函数执行完后,事件对象的属性会被清空。因此,异步访问事件属性会失效(需用e.persist()保留)。
React 17后移除了事件池,事件对象不再被复用,无需e.persist()

总结

场景原生事件React合成事件
传播阶段处理addEventListener(..., true)绑定捕获事件名加Capture后缀(如onClickCapture
stopPropagation()阻止所有阶段的传播(包括到React根节点)仅阻止合成事件传播,不影响原生事件传播
preventDefault()阻止默认行为,不影响传播同原生,需显式调用(return false无效)
事件绑定方式直接绑定到DOM元素委托到根节点,通过组件函数分发

理解这些差异的核心是:React合成事件是“模拟”原生事件的抽象层,其传播机制依赖原生事件的冒泡,但行为上做了统一和限制,以适配组件化开发需求。

http://www.dtcms.com/a/561234.html

相关文章:

  • React Hooks:提升前端开发效率的关键
  • Apache Tomcat 介绍
  • 国网公司网站建设宠物网站的目的
  • 怎么找做网站的外包公司二级域名是什么
  • CentOS 7/8/9 一键安装 Python 3.10+ 并配置默认版本
  • Harmony鸿蒙开发0基础入门到精通Day08--JavaScript篇
  • OpenCV(十八):绘制文本
  • Arbess实践指南(3) - 使用Arbess+sourcefare+PostIn实现Java项目自动化部署 + 代码扫描 + 接口自动化测试
  • 一,PCB介绍
  • 重庆网站建设机构科技进步是国防强大的重要的保证
  • asp网站用什么数据库做网站怎么导入源码
  • 【Docker】容器操作和实战
  • 阿里巴巴网站如何做免费推广wordpress首页文章轮播
  • 缓存三大问题及解决方案
  • 深度学习周报(10.27~11.2)
  • 怎么做便民信息网站原创小说手机网站制作需要多少钱
  • Java外功精要——Spring AOP
  • 线程从共享队列取任务的底层机制
  • 一站式网站建设报价怎样做商城网站
  • 宜春公司网站建设网页改进方案
  • 「经典数字题」集合 | C/C++
  • centos7实测
  • 【3DV 进阶-5】3D生成中 Inductive Bias (归纳偏置)的技术路线图
  • HOT100题打卡第26天——动态规划
  • 第五章 二项式系数
  • 制作网站语言网络营销方法有什么
  • 合肥网站建站推广从零开始做电影网站
  • 电商Web 渗透测试小小清单
  • 做信息流推广需要建立网站么最基本的网站设计
  • 基于双向时序卷积网络与门控循环单元(BiTCN-GRU)混合模型的时间序列预测MATLAB代码