React系列之合成事件与事件处理机制

news2024/9/22 11:31:45

文章目录

  • React事件处理机制
    • 原生事件的事件机制
      • 事件代理(事件委托)
    • 合成事件
      • 使用合成事件目的
      • 合成事件原生事件区别
      • 事件池
    • 原生事件和React事件的执行顺序
      • e.stopPropagation()
    • React17事件机制的修改

React事件处理机制

react 事件机制基本理解:react 基于浏览器的事件机制,自身实现了一套自己的事件机制,包括事件注册、事件的合成、事件冒泡、事件派发等。
react 的所有事件并没有绑定到具体的dom节点上而是绑定在了 document 上,然后由统一的事件处理程序来处理,同时也是基于浏览器的事件机制(冒泡),所有节点的事件都会在 document 上触发。

React 的事件处理机制可以分为两个阶段:

  • 初始化渲染时在 root 节点上注册原生事件;
  • 原生事件触发时模拟、目标和冒泡阶段派发合成事件。
    通过这种机制,冒泡的原生事件类型最多在 root 节点上注册一次,节省内存开销。且 React 为不同类型的事件定义了不同的处理优先级,从而让用户代码及时响应高优先级的用户交互,提升用户体验。

合成事件是 React 模拟原生 DOM 事件所有能力的一个事件对象,它可以兼容所有浏览器,也拥有和浏览器原生事件相同的接口。

原生事件的事件机制

在这里插入图片描述
事件流向分为三个阶段:捕获阶段、目标阶段、冒泡阶段。
捕获阶段是指事件响应从最外层的Window开始逐层向内层推进,直到具体的目标元素。
目标阶段是触发事件的目标元素。
冒泡阶段与捕获阶段相反,事件的响应是从最底层开始一层层向外传递到最外层的Window。

我们可以通过element.addEventListener()设置一个元素的事件模型为冒泡事件还是捕获事件。
element.addEventListener(type, listener, useCapture)
type:监听的事件类型(例’click’)
listener:事件的回调函数
useCapture:默认值为false,表示元素事件模型为事件冒泡,设为true时为事件捕获。

在这里插入图片描述

事件代理(事件委托)

事件代理(也称为事件委托)是一种利用DOM事件机制,通过将事件处理程序添加到父元素而不是每个子元素上来提高性能的技术。当子元素上的事件触发时,事件会冒泡/捕获到父元素,然后由父元素上的事件处理程序进行处理。
例对于列表元素,我们希望将用户点击了哪个item打印出来,通常我们可以给每个item注册点击事件监听器,但通过事件代理,可以将多个事件监听器减少为一个,这样可以减少重复工作,也可以减少内存。还可以使新增元素动态绑定事件。

var items = document.getElementById('item-list');
//事件捕获实现事件代理
items.addEventListener('click', (e) => {console.log('捕获:click ',e.target.innerHTML)}, true);
//事件冒泡实现事件代理
items.addEventListener('click', (e) => {console.log('冒泡:click ',e.target.innerHTML)}, false);

事件代理既可以通过事件冒泡来实现,也可以通过事件捕获来实现。

合成事件

React 合成事件(SyntheticEvent)是 React 模拟原生 DOM 事件所有能力的一个事件对象,即浏览器原生事件的跨浏览器包装器。它根据 W3C 规范来定义合成事件,兼容所有浏览器,拥有与浏览器原生事件相同的接口。

即在react中,我们绑定的事件onClick等,并不是原生事件,而是由原生事件合成的React事件,比如 click 事件合成为 onClick 事件。比如 blur, change, input, keydown, keyup, 合成为 onChange。可以通过 e.nativeEvent 属性获取原生事件。

使用合成事件目的

  • 方便事件统一管理
  • 进行浏览器兼容,实现更好的跨平台
  • 避免垃圾回收:事件对象可能会被频繁创建和回收,因此 React 引入事件池,在事件池中获取或释放事件对象。即 React 事件对象不会被释放掉,而是存放进一个数组中,当事件触发,就从这个数组中弹出,避免频繁地去创建和销毁(垃圾回收) 。

合成事件原生事件区别

命名方式不同:原生事件命名为纯小写,合成事件命名用小驼峰。
事件处理函数写法不同:原生事件中函数为字符串,合成事件里为函数。
阻止默认行为方式不同:原生事件中可以返回 false 来阻止默认行为,合成事件里需要显式调用 e.preventDefault() 来阻止。

事件池

合成事件对象池,是 React 事件系统提供的一种性能优化方式。合成事件对象在事件池统一管理,不同类型的合成事件具有不同的事件池。
React 事件池仅支持在 React16 及更早版本中,在 React17 已经不使用事件池。

SyntheticEvent 对象会被放入池中统一管理。这意味着 SyntheticEvent 对象可以被复用,当所有事件处理函数被调用之后,其所有属性都会被置空。例如,以下代码是无效的:

function handleChange(e) {
  // This won't work because the event object gets reused.
  setTimeout(() => {
    console.log(e.target.value); // Too late!
  }, 100);
}

https://zh-hans.legacy.reactjs.org/docs/legacy-event-pooling.html

原生事件和React事件的执行顺序

React 所有事件都挂载在 document 对象上。当真实 DOM 元素触发事件,会冒泡到 document 对象后,再处理 React 事件。
所以会先执行原生事件,然后处理 React 事件,最后真正执行 document 上挂载的事件。

原生事件(阻止冒泡)会阻止合成事件的执行;合成事件(阻止冒泡)不会阻止原生事件的执行。

e.stopPropagation()

e.stopPropagation() 可以阻止合成事件在组件树中的冒泡传播。事件本身还都是在 document 上执行。不能阻止原生事件的冒泡传播。
原生事件中如果执行了 stopPropagation 方法,则会导致其他 React 事件失效。因为所有元素的事件将无法冒泡到document上。

React17事件机制的修改

  • 事件统一绑定container上,ReactDOM.render(app, container);而不是document上,这样好处是有利于微前端的,微前端一个前端系统中可能有多个应用,如果继续采取全部绑定在document上,那么可能多应用下会出现问题。比如如果你在一个 React 子应用的 React 事件中调用了 e.stopPropagation(),无法阻止事件冒泡到外部树,因为真实的事件早已传播到 document。
  • React17 对齐了浏览器原生标准。比如 onScroll 事件不再进行事件冒泡。onFocus 和 onBlur 使用原生 focusin, focusout 合成。
  • React17 取消事件池复用。“它并不会提高现代浏览器的性能,甚至还会使经验丰富的开发者一头雾水” -> React 在旧浏览器中重用了不同事件的事件对象,以提高性能,并将所有事件字段在它们之前设置为 null。在 React 16 及更早版本中,使用者必须调用 e.persist() 才能正确的使用该事件,或者正确读取需要的属性。

在这里插入图片描述

https://zh-hans.legacy.reactjs.org/blog/2020/08/10/react-v17-rc.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1552768.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Maven配置国内镜像-阿里云仓库镜像

使用自己安装maven环境时&#xff1a; 打开解压目录下conf/settings.xml文件 使用Idea自带的Maven时&#xff1a; 打开Idea安装路径\plugins\maven\lib\maven3\conf\settings.xml文件 在mirrors节点中加入如下配置&#xff1a; <!-- 加入如下mirror节点 使用国内阿里云仓…

fastadmin学习05-开启debug以及配置

FastAdmin 框架提供了对 .env 环境变量配置的支持&#xff0c;并附带一个默认示例文件 .env.sample。在安装后&#xff0c;框架并不会自动启用 env 环境变量&#xff0c;需要手动将 .env.sample 复制为 .env 并进行配置。 如果不开启.env会读取database.php中的配置 下面测试…

鸿蒙OS开发实例:【页面传值跳转】

介绍 本篇主要介绍如何在HarmonyOS中&#xff0c;在页面跳转之间如何传值 HarmonyOS 的页面指的是带有Entry装饰器的文件&#xff0c;其不能独自存在&#xff0c;必须依赖UIAbility这样的组件容器 如下是官方关于State模型开发模式下的应用包结构示意图&#xff0c;Page就是…

基于单片机智能温控风扇调速系统设计

**单片机设计介绍&#xff0c;基于单片机智能温控风扇调速系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机智能温控风扇调速系统设计概要主要涉及到硬件设计、温度检测、风扇控制以及可能的拓展功能等方面。以…

Machine Learning机器学习之贝叶斯网络(BayesianNetwork)

目录 前言 算法提出背景&#xff1a; 贝叶斯算法特点&#xff1a; 一、贝叶斯定理 二、朴素贝叶斯分类模型 1、朴素贝叶斯分类模型&#xff08;Naive Bayes Classifier&#xff09; 2、原理 2.1 朴素贝叶斯假设 2.2条件独立性假设 2.3后验概率计算 2.4类别预测 2.5小结 3、建模…

Postman测试含有变量的接口的方法

1.在路径中用/&#xff1a;设置变量名 2.设置token验证 3.填写参数

Vue 04 Vue 中的 Ajax、slot 插槽

Vue学习 Vue 0401 Vue中的Ajax服务器准备axios使用跨域问题解决Vue-CLI 配置代理1Vue-CLI 配置代理2案例: 用户搜索vue-resource 02 slot插槽默认插槽具名插槽作用域插槽slot总结 Vue 04 B站 Vue全家桶&#xff08;BV1Zy4y1K7SH&#xff09; 学习笔记 Vue 中的 ajax 01 Vue中的…

Unity 学习日记 12.小球撞击冰块游戏

目录 1.准备场景 2.让小球动起来 3.用鼠标把小球甩出去 4.加入鼠标点击小球的判断 5.小球与冰块的碰撞测试 6.撞击后销毁冰块 ​编辑 7.显示游戏计时 8.显示扔球次数 9.显示剩余冰块个数 10.游戏结束 11.完整代码 下载源码 UnityPackage 最终效果&#xff1a; 1.准…

Idea2023.3.6版本无法启动设置界面-settings界面打不开无反应---IntelliJ Idea工作笔记013

先说一下网上有,把某个文件删除的 有说是因为汉化问题的 可以看到,其实都不是,这样弄就好了,很简单 Please report thisjava.lang.ClassCastException: class [Lcom.intellij.execution.filters.CompositeInputFilter$InputFilterWrapper; cannot be cast to class java.uti…

关于使用vscode搭建c/c++编程环境

目录 关于使用vscode搭建c/c编程环境一、前言二、安装 IDE 二、安装TDM-GCC安装三、安装C/C环境四、编写代码并进行编译 关于使用vscode搭建c/c编程环境 一、前言 一直觉得vscode是生产强有力的生产工具&#xff0c;基于此&#xff0c;做一篇学习笔记进行记录。 二、安装 ID…

洛谷 P1379 八数码难题

代码如下&#xff1a; #include<bits/stdc.h> using namespace std; struct node{string s;int pos; }star,en; map<string,int>mp[2]; queue<node>q[2]; int main(){cin>>star.s;en.s"123804765";for(int i0;i<9;i){if(star.s[i]0) sta…

服务器停止解析域名,但仍然可以访问到

1.centos7 如何刷新dns缓存 在CentOS 7上&#xff0c;DNS缓存由nscd&#xff08;Name Service Cache Daemon&#xff09;管理&#xff0c;如果系统上安装了nscd&#xff0c;可以通过清除nscd缓存来刷新DNS缓存。 要刷新DNS缓存&#xff0c;请执行以下命令&#xff1a; sudo …

【XXL-JOB】执行器架构设计和源码解析

简介 XXL-JOB是一个分布式任务调度平台&#xff0c;其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线&#xff0c;开箱即用。 XXL-JOB分为B/S架构&#xff0c;调用中心是XXL-JOB服务端&#xff0c;执行器是客户端。 调度中心核…

入门指南|营销中人工智能生成内容的主要类型 [新数据、示例和技巧]

由于人工智能技术的进步&#xff0c;内容生成不再是一项令人头疼的任务。随着人工智能越来越多地接管手动内容制作任务&#xff0c;营销人员明智的做法是了解现有的不同类型的人工智能生成内容&#xff0c;以及哪些内容从中受益最多。这些工具可以帮助我们制作对您的受众和品牌…

3.28C++

复数类的实现&#xff0c;写出三种构造函数&#xff0c;算术运算符、关系运算符、逻辑运算符重载尝试实现自增、自减运算符的重载 #include <iostream> using namespace std; class Num {int rel; //实部int vir; //虚部 public:Num():rel(2),vir(1){}Num(int rel,…

若依 3.8.7版本springboot前后端分离 整合mabatis plus

1.去掉mybatis 这一步我没有操作&#xff0c;看别人的博客有说不去掉可能冲突&#xff0c;也可能不冲突&#xff0c;我试下来就没去掉如需要去除&#xff0c;到总的pom.xml中properties标签下的<mybatis-spring-boot.version>x.x.x</mybatis-spring-boot.version>…

如何在极狐GitLab 自定义 Pages 域名、SSL/TLS 证书

本文作者&#xff1a;徐晓伟 GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 本文主要讲述了在极狐GitLab 用户…

深圳区块链交易所app系统开发,撮合交易系统开发

随着区块链技术的迅速发展和数字资产市场的蓬勃发展&#xff0c;区块链交易所成为了数字资产交易的核心场所之一。在这个快速发展的领域中&#xff0c;区块链交易所App系统的开发和撮合交易系统的建设至关重要。本文将探讨区块链交易所App系统开发及撮合交易系统的重要性&#…

包子凑数(蓝桥杯,闫氏DP分析法)

题目描述&#xff1a; 小明几乎每天早晨都会在一家包子铺吃早餐。 他发现这家包子铺有 N 种蒸笼&#xff0c;其中第 i 种蒸笼恰好能放 Ai 个包子。 每种蒸笼都有非常多笼&#xff0c;可以认为是无限笼。 每当有顾客想买 X 个包子&#xff0c;卖包子的大叔就会迅速选出若干笼…

解决:PytorchStreamWriter failed writing file data

文章目录 问题内容问题分析解决思路 问题内容 今天在炼丹的时候&#xff0c;我发现模型跑到140步的时候保存权重突然报了个问题&#xff0c;详细内容如下&#xff1a; Traceback (most recent call last):File "/public/home/dyedd/.conda/envs/diffusers/lib/python3.8…