React合成事件的原理是什么
事件介绍
什么是事件?
事件是在编程时系统内发生的动作或者发生的事情,而开发者可以某种方式对事件做出回应,而这里有几个先决条件
-
事件对象
-
给事件对象注册事件,当事件被触发后需要做什么
-
事件触发
举个例子
在机场等待检票,听到广播后排队检票
-
事件对象,也就是检票事件
-
事件注册/监听,也就是我们在机场等待的时候
-
事件触发,广播响起开始检票
-
事件触发之后的回调,我们开始排队...
// 检票事件
var event = new Event('check-ticket');
// 事件注册,并编写回调
elem.addEventListener('check-ticket', function (e) { // 开始排队LiningUp()
});
// 事件触发,广播开始检票
elem.dispatchEvent(event);
React合成事件基础知识
什么是合成事件?
不是浏览器本身触发的事件,自己创建和触发的事件。
在React中事件的写法和原生事件写法的区别?
-
React 事件的命名采用小驼峰式(camelCase),而不是纯小写。
-
使用 JSX 语法时你需要传入一个函数作为事件处理函数,而不是一个字符串。
// HTML中的写法
<button onclick="handleClick()">Activate Lasers
</button>
// React中的写法
<button onClick={handleClick}>Activate Lasers
</button>
为什么会有合成事件?
-
对事件进行归类,可以在事件产生的任务上包含不同的优先级
-
提供合成事件对象,抹平浏览器的兼容性差异
合成事件机制简述
提供了一种“顶层注册,事件收集,统一触发”的事件机制
-
“顶层注册”,其实是在root元素上绑定一个统一的事件处理函数
-
“事件收集”, 事件触发时(实际上是root上的事件处理函数被执行),构造合成事件对象,按照冒泡或捕获的路径去组件中收集真正的事件处理函数
-
“统一触发”,在收集过程之后,对收集的事件逐一执行,并共享同一个合成事件对象
React合成事件实现原理
事件注册
时机:在fiber
节点进入render
阶段的complete
阶段时,名为onClick的props会被识别为事件进行处理
function setInitialDOMProperties(tag: string,domElement: Element,rootContainerElement: Element | Document,nextProps: Object,isCustomComponentTag: boolean,
): void {for (const propKey in nextProps) {if (!nextProps.hasOwnProperty(propKey)) {...} else if (registrationNameDependencies.hasOwnProperty(propKey)) {// 如果propKey属于事件类型,则进行事件绑定ensureListeningTo(rootContainerElement, propKey, domElement);}}}
}
// registrationNameDependencies为合成事件名和真实事件的映射,格式如下:
{onChange: ['change', 'click', 'focusin', 'focusout', 'input', 'keydown', 'keyup', 'selectionchange']onChangeCapture: ['change', 'click', 'focusin', 'focusout', 'input', 'keydown', 'keyup', 'selectionchange']onClick: ['click']
}
调用ensureListeningTo
进行事件绑定
然后调用DOMPluginEventSystem.js中的addTrappedEventListener
进行事件注册,而监听器listener是React通过createEventListenerWrapperWithPriority
创建出优先级不同的时间监听包装器
总的来说,会有三种事件监听包装器:
-
dispatchDiscreteEvent: 处理离散事件
-
dispatchUserBlockingUpdate:处理用户阻塞事件
-
dispatchEvent:处理连续事件
事件触发-事件监听器做了什么
负责以不同的优先级权重来触发真正的事件流程
在createEventListenerWrapperWithPriority
中,根据eventPriority
事件优先级不同调用事件dispatchDiscreteEvent
、dispatchUserBlockingUpdate
、dispatchUserBlockingUpdate
、dispatchEvent
进行事件绑定
export function createEventListenerWrapperWithPriority(targetContainer: EventTarget,domEventName: DOMEventName,eventSystemFlags: EventSystemFlags,
): Function {const eventPriority = getEventPriorityForPluginSystem(domEventName);let listenerWrapper;switch (eventPriority) {case DiscreteEvent:listenerWrapper = dispatchDiscreteEvent;break;case UserBlockingEvent:listenerWrapper = dispatchUserBlockingUpdate;break;case ContinuousEvent:default:listenerWrapper = dispatchEvent;break;}return listenerWrapper.bind(null,domEventName,eventSystemFlags,targetContainer,);
}
在每一个事件绑定函数中,会调用dispatchEventsForPlugins
函数
-
合成事件,放入dispatchQueue中
而dispatchQueue由两部分组成
-
合成事件对象
-
多个listeners(可以共用一个合成事件对象)
-
-
执行事件执行路径下的事件,从
dispatchQueue
中取出事件对象events
和具体执行路径listeners
,然后遍历执行
function dispatchEventsForPlugins(domEventName: DOMEventName,eventSystemFlags: EventSystemFlags,nativeEvent: AnyNativeEvent,targetInst: null | Fiber,targetContainer: EventTarget,
): void {const nativeEventTarget = getEventTarget(nativeEvent);const dispatchQueue: DispatchQueue = [];// 通过不同事件类型插件进行事件对象合成,将合成事件放入事件队列中:dispatchQueue中extractEvents(dispatchQueue,domEventName,targetInst,nativeEvent,nativeEventTarget,eventSystemFlags,targetContainer,);// 执行dispatchQueue中具体事件执行路径下的事件processDispatchQueue(dispatchQueue, eventSystemFlags);
}
// 通过extractEvents合成的dispatchQueue的格式如下
[{// event是合成事件对象event, // 具体的事件执行路径,currentTarget、listener等信息listeners: [{currentTarget: div.counter,instance: FiberNode {tag: 5, key: null, elementType: 'div', type: 'div', stateNode: div.counter, …},listener: e => {…}},{currentTarget: div.counter-parent,instance: FiberNode {tag: 5, key: null, elementType: 'div', type: 'div', stateNode: div.counter, …},listener: e => {…}}] }
]
React中模拟冒泡和捕获
原理:收集的事件放在dispatchQueue
数组中,而冒泡和捕获的区别在于执行时机和顺序,那么我们只需要对数组按照不同顺序循环执行即可
function processDispatchQueueItemsInOrder(event: ReactSyntheticEvent,dispatchListeners: Array<DispatchListener>,inCapturePhase: boolean,
): void {let previousInstance;if (inCapturePhase) {// 事件捕获倒序循环for (let i = dispatchListeners.length - 1; i >= 0; i--) {const {instance, currentTarget, listener} = dispatchListeners[i];if (instance !== previousInstance && event.isPropagationStopped()) {return;}// 执行事件,传入event对象,和currentTargetexecuteDispatch(event, listener, currentTarget);previousInstance = instance;}} else {// 事件冒泡正序循环for (let i = 0; i < dispatchListeners.length; i++) {const {instance, currentTarget, listener} = dispatchListeners[i];// 如果事件对象阻止了冒泡,则return掉循环过程if (instance !== previousInstance && event.isPropagationStopped()) {return;}executeDispatch(event, listener, currentTarget);previousInstance = instance;}}
}
相关文章:
React合成事件的原理是什么
事件介绍 什么是事件? 事件是在编程时系统内发生的动作或者发生的事情,而开发者可以某种方式对事件做出回应,而这里有几个先决条件 事件对象 给事件对象注册事件,当事件被触发后需要做什么 事件触发 举个例子 在机场等待检票…...

Arduino-交通灯
LED交通灯实验实验器件:■ 红色LED灯:1 个■ 黄色LED灯:1 个■ 绿色LED灯:1 个■ 220欧电阻:3 个■ 面包板:1 个■ 多彩杜邦线:若干实验连线1.将3个发光二极管插入面包板,2.用杜邦线…...

【论文笔记】Manhattan-SDF == ZJU == CVPR‘2022 Oral
Neural 3D Scene Reconstruction with the Manhattan-world Assumption 本文工作:基于曼哈顿世界假设,重建室内场景三维模型。 1.1 曼哈顿世界假设 参考阅读文献:Structure-SLAM: Low-Drift Monocular SLAM in Indoor EnvironmentsIEEE IR…...

好消息!Ellab(易来博)官方微信公众号开通了!携虹科提供专业验证和监测解决方案
自1949年以来,丹麦Ellab一直通过全球范围内的验证和监测解决方案,协助全球生命科学和食品公司优化和改进其流程的质量。Ellab全面的无线数据记录仪,热电偶系统,无线环境监测系统,校准设备,软件解决方案等等…...

想要去字节跳动面试Android岗,给你这些面试知识点
关于面试字节跳动,我总结一些面试点,希望可以帮到更多的小伙伴,由于篇幅问题这里没有把全部的面试知识点问题都放上来!!目录:1.网络2.Java 基础&容器&同步&设计模式3.Java 虚拟机&内存结构…...
Java的Lambda表达式的使用
Lambda表达式是Java 8中引入的一个重要特性,它是一种简洁而强大的语法结构,可以用于替代传统的匿名内部类。 Lambda表达式的语法结构如下: (parameters) -> expression或者 (parameters) -> { statements; }其中,paramet…...

Spring MVC 源码 - HandlerMapping 组件(三)之 AbstractHandlerMethodMapping
HandlerMapping 组件HandlerMapping 组件,请求的处理器匹配器,负责为请求找到合适的 HandlerExecutionChain 处理器执行链,包含处理器(handler)和拦截器们(interceptors)handler 处理器是 Objec…...

超店有数,为什么商家要使用tiktok达人进行营销推广呢?
近几年互联网发展萌生出更多的短视频平台,而tittok这个平台在海外也越来越火爆。与此同时,很多商家也开始用tiktok进行营销推广。商家使用较多的方式就是达人营销,这种方法很常见且转化效果不错。那为什么现在这么多商家喜欢用tiktok达人进行…...

【分享】订阅万里牛集简云连接器同步企业采购审批至万里牛系统
方案场景 面临着数字化转型的到来,不少公司希望实现业务自动化需求,公司内部将钉钉作为办公系统,万里牛作为ERP系统,两个系统之前的数据都储存在各自的后台,导致数据割裂,数据互不相通,人工手动…...

C++类和对象_02----对象模型和this指针
目录C对象模型和this指针1、成员变量和成员函数分开存储1.1、空类大小1.2、非空类大小1.3、结论2、this指针概念2.1、解决名称冲突2.2、在类的非静态成员函数中返回对象本身,可使用return *this2.3、拷贝构造函数返回值为引用的时候,可进行链式编程3、空…...
瑞芯微RK3568开发:烧录过程
进入rk3568这款芯片的烧录模式共有3种方式,先讲需要准备的环境要求。 一、软硬件环境 1、配套sdk版本的驱动DriverAssitant_vx.x.x和RKDevTool_Release_vx.x,版本不对应可能无法烧录,建议直接在sdk压缩包里获取; 2、如果正确安…...

【数据结构】——树和二叉树的概念
目录 1.树概念及结构 1.1树的概念 1.2 树的相关性质 1.3 树的表示 1.4 树在实际中的运用(表示文件系统的目录树结构) 2.二叉树概念及结构 2.1二叉树概念 2.2 特殊的二叉树 2.3 二叉树的性质 1.树概念及结构 1.1树的概念 树是一种非线性的数据结构…...

Meta分析在生态环境领域里的应用
Meta分析(Meta Analysis)是当今比较流行的综合具有同一主题的多个独立研究的统计学方法,是较高一级逻辑形式上的定量文献综述。20世纪90年代后,Meta分析被引入生态环境领域的研究,并得到高度的重视和长足的发展&#x…...

PrivateLoader PPI服务发现RisePro恶意软件窃取分发信息
称为PrivateLoader的按安装付费(PPI)软件下载器服务正用于恶意软件RisePro的信息窃取。Flashpoint 于 2022 年 12月13日发现了新的窃取者,此前发现了在名为Russian Market的非法网络犯罪市场上使用该恶意软件泄露的“几组日志”。RisePro是一…...
SQL93 返回购买 prod_id 为 BR01 的产品的所有顾客的电子邮件(一)
描述你想知道订购 BR01 产品的日期,有表OrderItems代表订单商品信息表,prod_id为产品id;Orders表代表订单表有cust_id代表顾客id和订单日期order_date;Customers表含有cust_email 顾客邮件和cust_id顾客idOrderItems表prod_idorde…...

Git ---- 概述
Git ---- 概述1. 何为版本控制2. 为什么需要版本控制3. 版本控制的工具集中式版本控制工具分布式版本控制工具4. Git 简史5. Git 工作机制6. Git 和代码托管中心Git 是一个免费的、开源的分布式版本控制系统,可以快速高效地处理从小型到大型的各种项目。 Git 易于学…...

用 tensorflow.js 做了一个动漫分类的功能(二)
前言:前面已经通过采集拿到了图片,并且也手动对图片做了标注。接下来就要通过 Tensorflow.js 基于 mobileNet 训练模型,最后就可以实现在采集中对图片进行自动分类了。这种功能在应用场景里就比较多了,比如图标素材站点࿰…...

小林coding
一、图解网络 问大家,为什么要有TCP/Ip网络模型? 对于同一台设备上的进程通信,有很多种方式,比如有管道、消息队列、共享内存、信号等方式,对于不同设备上的进程通信,就需要有网络通信,而设备是…...

操作系统真相还原_第6章:完善内核
文章目录6.1 函数调用约定简介6.2 汇编语言和C语言混合编程汇编调用CC调用汇编6.3 实现打印函数流程程序编译并写入硬盘执行6.4 内联汇编简介汇编语言AT&T语法基本内联汇编扩展内联汇编6.1 函数调用约定简介 调用约定: calling conventions 调用函数时的一套约…...

SmoothNLP新词发现算法的改进实现
SmoothNLP新词发现算法的改进实现 背景介绍 新词发现也叫未登录词提取,依据 《统计自然语言处理》(宗成庆),中文分词有98%的错误来自"未登录词"。即便早就火遍大江南北的Bert也不能解决"未登录词"的Encoding问题,便索性…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...

大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...

DBAPI如何优雅的获取单条数据
API如何优雅的获取单条数据 案例一 对于查询类API,查询的是单条数据,比如根据主键ID查询用户信息,sql如下: select id, name, age from user where id #{id}API默认返回的数据格式是多条的,如下: {&qu…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

网站指纹识别
网站指纹识别 网站的最基本组成:服务器(操作系统)、中间件(web容器)、脚本语言、数据厍 为什么要了解这些?举个例子:发现了一个文件读取漏洞,我们需要读/etc/passwd,如…...

AI+无人机如何守护濒危物种?YOLOv8实现95%精准识别
【导读】 野生动物监测在理解和保护生态系统中发挥着至关重要的作用。然而,传统的野生动物观察方法往往耗时耗力、成本高昂且范围有限。无人机的出现为野生动物监测提供了有前景的替代方案,能够实现大范围覆盖并远程采集数据。尽管具备这些优势…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...