文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

React合成事件的原理是什么

2023-07-02 16:12

关注

这篇文章主要讲解了“React合成事件的原理是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“React合成事件的原理是什么”吧!

事件介绍

什么是事件?

事件是在编程时系统内发生的动作或者发生的事情,而开发者可以某种方式对事件做出回应,而这里有几个先决条件

举个栗子

在机场等待检票,听到广播后排队检票

代码实现

// 检票事件var event = new Event('check-ticket');// 事件注册,并编写回调elem.addEventListener('check-ticket', function (e) {   // 开始排队  LiningUp()});// 事件触发,广播开始检票elem.dispatchEvent(event);

React合成事件基础知识

什么是合成事件?

不是浏览器本身触发的事件,自己创建和触发的事件。

在React中事件的写法和原生事件写法的区别?

// HTML中的写法<button onclick="handleClick()">  Activate Lasers</button>// React中的写法<button onClick={handleClick}>  Activate Lasers</button>

为什么会有合成事件?

合成事件机制简述

提供了一种“顶层注册,事件收集,统一触发”的事件机制

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创建出优先级不同的时间监听包装器

总的来说,会有三种事件监听包装器:

事件触发-事件监听器做了什么

负责以不同的优先级权重来触发真正的事件流程

createEventListenerWrapperWithPriority中,根据eventPriority事件优先级不同调用事件dispatchDiscreteEventdispatchUserBlockingUpdatedispatchUserBlockingUpdatedispatchEvent进行事件绑定

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函数

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对象,和currentTarget      executeDispatch(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合成事件的原理是什么”的内容了,经过本文的学习后,相信大家对React合成事件的原理是什么这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯