React合成事件详解

react合成事件指的是react用js模拟了一个Dom事件流。(fiber树模拟Dom树结构) 合成事件的事件流在fiber树中发生捕获和冒泡。

从点击输入框开始

当你点击input输入框,react在根节点(注1)监听到focus事件(注2)(注3)。

如何从原生事件找到对应的虚拟Dom?

此时,react得到的信息只有原生事件对象(nativeEvent)。react通过nativeEvent对应的Dom(eventTarget),沿着Dom树向上找到距离该eventTarget最近的被react管理的Dom节点(注4)(注5),并获得对应的fiber A。

接着通过事件插件(注6),创建合成事件(注7)A。合成事件A被react视为模拟事件流中的事件源,fiber A被react视为事件目标。

合成事件流?

从fiber A出发向上(直到顶层fiber HostComponent为止)收集所有的host类型的fiber。 然后将收集到的fiber数组,从后向前(捕获),再从前向后(冒泡)遍历。每次遍历,会收集(注8)当前遍历项fiber节点的绑定的focus事件。之后(事件插件完成后,即合成事件生成好了)会按照收集的顺序执行foucs回调。 react就是这样模拟了事件流。

扩展

点击输入框引起多个事件

除了focus外,也触发了其他的事件--click等。react在根节点对不同类型的事件进行了监听,每监听到一种事件就会派发一次,多种类型的事件,会派发多次。 点击输入框,会先后触发focus和click。当focus事件的派发完后,就会派发click事件。 每次某个事件派发结束,会处理待处理的同步任务队列(flushSyncCallBackQueue)。

意料之外的render?

在NoMode模式下,多次派发事件且每个事件都改变了状态(如调用setState),则对应组件会被render多次。 在本例中,点击input输入框,如果给input绑定了focus事件和click事件并且事件回调都调用setState,input将会render两次。

为什么react中的input设置value后成为受控组件?

react中,在input设置了value属性的条件下,无论在输入框中输入什么,输入框的值都不会改变。除非你改变了input组件的state。 react在处理完模拟事件流后,会调用方法将一些意外的效果重置。 例如该场景,在input中输入了一个值,input输入框会出现你输入的值,但马上input的值会被对应的fiber的value属性更新(finishEventHander 重置受控组件)。 如果没有给input设置value则会忽略。

为什么合成事件属性有时无法访问?

因为react在事件流(捕获到冒泡)完后就将合成事件对象释放(SyntheticEvent.prototype.destructor 将合成事件对象的属性重置)。

react如何模拟事件的阻止冒泡、阻止默认行为?

react按照事件流顺序执行回调,在执行前会检查当前合成事件对象是否处于阻止冒泡的状态,如果是,则终止事件流。 react的合成事件对象原型对原生函数进行增强。对原生事件方法的阻止冒泡、阻止默认行为进行了封装(内部也调用原生事件的方法)。

注释

注1:根节点,在 react-v16 为 document ,在 react-v17 为挂载容器Dom
注2:focus事件并不是冒泡事件,react对非冒泡事件在捕获阶段监听
注3:根节点对所有事件进行了监听,除了特别例外submit、reset、invalid和媒体事件等
注4:react将fiber树挂载到Dom树上时,每个宿主(host)类型fiber节点与Dom节点一一对应,并链接
注5:向上查找是因为可能子Dom节点并不是被react管理的,如第三库滚动插件等
注6:为了模拟Dom事件,react进行的补充
注7:react内部一个构造函数的实例,合成事件的部分属性来源于nativeEvent。合成事件与fiber关联
注8:收集而不是执行。因为react针对某一类型事件的做了批处理

以上就是React合成事件详解的详细内容,更多关于React合成事件的资料请关注我们其它相关文章!

(0)

相关推荐

  • 详解react关于事件绑定this的四种方式

    在react组件中,每个方法的上下文都会指向该组件的实例,即自动绑定this为当前组件,而且react还会对这种引用进行缓存,以达到cpu和内存的最大化.在使用了es6 class或者纯函数时,这种自动绑定就不复存在了,我们需要手动实现this的绑定 React事件绑定类似于DOM事件绑定,区别如下: 1.React事件的用驼峰法命名,DOM事件事件命名是小写 2.通过jsx,传递一个函数作为event handler,而不是一个字符串. 3.React事件不能通过返回false来阻止默认事件,

  • React+Antd+Redux实现待办事件的方法

    之前也是写过一篇关于Redux的文章,来简单理解一下Redux,以及该如何使用.今天我就来分享一个也是入门级别的,React+Redux+antd来实现简单的待办事件.同时也讲讲自己对Redux的理解.先来看一张图吧: 我们简单的比喻来让我们更加好的理解Redux,我们这样比喻(图书馆借书): 1.React Component:借书人 2.Action Creators:你要说你要借书这句话,肯定要说话吧,就是一句话:我要借书 3.Store:图书馆管理员 4.Reducer:图书馆管理员肯定

  • 通过实例学习React中事件节流防抖

    节流 方法一 import Throttle from 'lodash-decorators/throttle'; export default class Search extends Component { constructor(props) { super(props) this.handleSearch = this.handleSearch.bind(this); } handleSubmit = (e) => { e.preventDefault(); this.handleSea

  • React事件机制源码解析

    React v17里事件机制有了比较大的改动,想来和v16差别还是比较大的. 本文浅析的React版本为17.0.1,使用ReactDOM.render创建应用,不含优先级相关. 原理简述 React中事件分为委托事件(DelegatedEvent)和不需要委托事件(NonDelegatedEvent),委托事件在fiberRoot创建的时候,就会在root节点的DOM元素上绑定几乎所有事件的处理函数,而不需要委托事件只会将处理函数绑定在DOM元素本身. 同时,React将事件分为3种类型--d

  • React中阻止事件冒泡的问题详析

    前言 最近在研究react.redux等,网上找了很久都没有完整的答案,索性自己整理下,这篇文章就来给大家介绍了关于React阻止事件冒泡的相关内容,下面话不多说了,来一起看看详细的介绍吧 在正式开始前,先来看看 JS 中事件的触发与事件处理器的执行. JS 中事件的监听与处理 事件捕获与冒泡 DOM 事件会先后经历 捕获 与 冒泡 两个阶段.捕获即事件沿着 DOM 树由上往下传递,到达触发事件的元素后,开始由下往上冒泡. IE9 及之前的版本只支持冒泡 |  A  --------------

  • React学习之JSX与react事件实例分析

    本文实例讲述了React学习之JSX与react事件.分享给大家供大家参考,具体如下: 1.JSX 1.1.表达式 在React中使用JSX来描述HTML页面,而且可以与js混合使用,使用JavaScript表达式时要将表达式包含在大括号里 const user = { firstName: 'Harper', lastName: 'Perez' }; const element = ( //将JSX语句保存在变量中 <h1> Hello, {formatName(user)}! {/* {}

  • 详细分析React 表单与事件

    本章节我们将讨论如何在 React 中使用表单. HTML 表单元素与 React 中的其他 DOM 元素有所不同,因为表单元素生来就保留一些内部状态. 在 HTML 当中,像 <input>, <textarea>, 和 <select> 这类表单元素会维持自身状态,并根据用户输入进行更新.但在React中,可变的状态通常保存在组件的状态属性中,并且只能用 setState() 方法进行更新. 一个简单的实例 在实例中我们设置了输入框 input 值 value =

  • React事件节流效果失效的原因及解决

    今天做react项目中,给一个 input onKeyDown 事件做节流,出现了节流效果失效. 问题代码: render() { return ( <div className="search-bar"> <input className="search-input" type="text" placeholder="请输入要搜索的用户名(英文)" onKeyDown={this.throttle(this

  • React事件处理的机制及原理

    React中的事件处理 在React元素中绑定事件有两点需要注意: (1)在React中,事件命名采用驼峰命名方式,而不是DOM元素中的小写字母命名方式.例如onclick要写成onClick,onchange要写成onChange等. (2)处理事件的响应函数要以对象的形式赋值给事件属性,而不是DOM中的字符串形式.例如在DOM中绑定一个点击事件应该写成: <button onclick="clickButton()"> Click </button> 而在R

  • React组件内事件传参实现tab切换的示例代码

    本文介绍了React组件内事件传参实现tab切换的示例代码,分享给大家,具体如下: 组件内默认onClick事件触发函数actionClick, 是不带参数的, 不带参数的写法: 如onClick= { actionItem } 带参数的写法, onClick = { this.activateButton.bind(this, 0) } 下面是一个向组件内函数传递参数的小例子 需求: 在页面的底部, 有四个按钮, 负责切换内容, 当按钮被点击时, 变为激活状态, 其余按钮恢复到未激活状态 分析

随机推荐