精品课网站建设 辽宁pc网站建设企业

bicheng/2026/1/24 13:12:33/文章来源:
精品课网站建设 辽宁,pc网站建设企业,网站搬家数据库配置,医生做网站不违法event 对象 1 #xff09; 概述 在生产事件对象的过程当中#xff0c;要去调用每一个 possiblePlugin.extractEvents 方法现在单独看下这里面的细节过程#xff0c;即如何去生产这个事件对象的过程 2 #xff09;源码 定位到 packages/events/EventPluginHub.js#L172 f…event 对象 1 概述 在生产事件对象的过程当中要去调用每一个 possiblePlugin.extractEvents 方法现在单独看下这里面的细节过程即如何去生产这个事件对象的过程 2 源码 定位到 packages/events/EventPluginHub.js#L172 function extractEvents(topLevelType: TopLevelType,targetInst: null | Fiber,nativeEvent: AnyNativeEvent,nativeEventTarget: EventTarget, ): ArrayReactSyntheticEvent | ReactSyntheticEvent | null {let events null;for (let i 0; i plugins.length; i) {// Not every plugin in the ordering may be loaded at runtime.const possiblePlugin: PluginModuleAnyNativeEvent plugins[i];if (possiblePlugin) {// 这里要去调用 每个 plugin 的 extractEvents 方法const extractedEvents possiblePlugin.extractEvents(topLevelType,targetInst,nativeEvent,nativeEventTarget,);if (extractedEvents) {events accumulateInto(events, extractedEvents);}}}return events; }注意这里的 possiblePlugin.extractEvents 我们专门专注下 changeEvent 的这个方法 定位到 packages/react-dom/src/events/ChangeEventPlugin.js#L263 const ChangeEventPlugin {eventTypes: eventTypes,_isInputEventSupported: isInputEventSupported,// 注意这里extractEvents: function(topLevelType,targetInst,nativeEvent,nativeEventTarget,) {// 在这个方法里面拿到了 targetNode// 因为这边传进来的呢是一个发布对象, 所以要通过这种方法拿到它的 nodeconst targetNode targetInst ? getNodeFromInstance(targetInst) : window;// 然后要经过一系列的判断主要去赋值了不同的 getTargetInstFunclet getTargetInstFunc, handleEventFunc;// 如果有返回这个instance那么我们就可以去创建这个event了这是什么意思呢// 就是说我们这个 event plugin, 在所有的事件触发的过程当中这个plugin都会被循环调用的// 它是没有通过事件名称来调用不同的plugin这么一个设置的// 所以这个判断是要放在每个pluggin里面自己去做。就是说根据这次触发的具体事件是什么// 来判断我们要不要为它创建一个event因为每个plugin在每次事件触发都会被调用// 如果我们都生成事件那么明显是不对的肯定要对自己这个 plugin 关心的事件来去为它生成这个事件if (shouldUseChangeEvent(targetNode)) {getTargetInstFunc getTargetInstForChangeEvent;} else if (isTextInputElement(targetNode)) {if (isInputEventSupported) {getTargetInstFunc getTargetInstForInputOrChangeEvent;} else {// polyfill 的这些先忽略getTargetInstFunc getTargetInstForInputEventPolyfill;handleEventFunc handleEventsForInputEventPolyfill;}} else if (shouldUseClickEvent(targetNode)) {getTargetInstFunc getTargetInstForClickEvent;}// 基于类型得到了最终的处理函数if (getTargetInstFunc) {const inst getTargetInstFunc(topLevelType, targetInst);if (inst) {// 创建 eventconst event createAndAccumulateChangeEvent(inst,nativeEvent,nativeEventTarget,);return event;}}if (handleEventFunc) {handleEventFunc(topLevelType, targetNode, targetInst);}// When blurring, set the value attribute for number inputsif (topLevelType TOP_BLUR) {handleControlledInputBlur(targetNode);}}, };进入 shouldUseChangeEvent function shouldUseChangeEvent(elem) {const nodeName elem.nodeName elem.nodeName.toLowerCase();return (nodeName select || (nodeName input elem.type file)); }这个判断其实就是主要来判断一下我们这个节点上面是否有changeevent并且是否应该用 change event 来进行一个触发因为react当中的 onchange 事件其实它是封装了各种不同的事件的比如说对于像我们输入文本的 input type‘text’ 的一个情况正常来讲应该绑定的是input事件而不是change事件因为change事件在有些浏览器里面要等到这个输入框blur的时候才会真正触发这个change事件对于input事件是我们每次有输入变化的时候都会触发的这个事件所以对于 select 还有 input type‘file’, 它们的change是非常明显的就是等到它们有内容变化的时候就会触发因为file是我们选择了一个文件之后它就会触发change事件而select我们选择了某一个 option 之后它也会触发这个change事件所以对于这种节点我们可以直接使用onchange来进行一个绑定这时候, getTargetInstFunc getTargetInstForChangeEvent; 进入 getTargetInstForChangeEventfunction getTargetInstForChangeEvent(topLevelType, targetInst) {// TOP_CHANGE 就是 changeif (topLevelType TOP_CHANGE) {return targetInst;} }// 注意 另外的文件中 // packages/react-dom/src/events/DOMTopLevelEventTypes.js#L41 export const TOP_CHANGE unsafeCastStringToDOMTopLevelType(change);// packages/events/TopLevelEventTypes.js#L27 export function unsafeCastStringToDOMTopLevelType(topLevelType: string, ): DOMTopLevelEventType {return topLevelType; }进入 isTextInputElement const supportedInputTypes: {[key: string]: true | void} {color: true,date: true,datetime: true,datetime-local: true,email: true,month: true,number: true,password: true,range: true,search: true,tel: true,text: true,time: true,url: true,week: true, };function isTextInputElement(elem: ?HTMLElement): boolean {// 获取 nodeNameconst nodeName elem elem.nodeName elem.nodeName.toLowerCase();// 判断在 input 的时候是否符合支持的type类型if (nodeName input) {return !!supportedInputTypes[((elem: any): HTMLInputElement).type];}if (nodeName textarea) {return true;}return false; }这里就是一个 boolean 类型的函数进行类型判断的 进入 getTargetInstForInputOrChangeEvent // packages/react-dom/src/events/ChangeEventPlugin.js#L229 function getTargetInstForInputOrChangeEvent(topLevelType, targetInst) {if (topLevelType TOP_INPUT || topLevelType TOP_CHANGE) {return getInstIfValueChanged(targetInst);} }// packages/react-dom/src/events/ChangeEventPlugin.js#L106 function getInstIfValueChanged(targetInst) {const targetNode getNodeFromInstance(targetInst);if (inputValueTracking.updateValueIfChanged(targetNode)) {return targetInst;} }// packages/react-dom/src/client/ReactDOMComponentTree.js#L69 export function getNodeFromInstance(inst) {if (inst.tag HostComponent || inst.tag HostText) {// In Fiber this, is just the state node right now. We assume it will be// a host component or host text.return inst.stateNode;}// Without this first invariant, passing a non-DOM-component triggers the next// invariant for a missing parent, which is super confusing.invariant(false, getNodeFromInstance: Invalid argument.); }进入 shouldUseClickEvent /*** SECTION: handle click event*/// checkbox 和 radio 的特殊处理 function shouldUseClickEvent(elem) {// Use the click event to detect changes to checkbox and radio inputs.// This approach works across all browsers, whereas change does not fire// until blur in IE8.const nodeName elem.nodeName;return (nodeName nodeName.toLowerCase() input (elem.type checkbox || elem.type radio)); }进入 getTargetInstForClickEvent function getTargetInstForClickEvent(topLevelType, targetInst) {if (topLevelType TOP_CLICK) {return getInstIfValueChanged(targetInst);} }进入 createAndAccumulateChangeEvent 创建事件对象 function createAndAccumulateChangeEvent(inst, nativeEvent, target) {const event SyntheticEvent.getPooled(eventTypes.change,inst,nativeEvent,target,);event.type change;// Flag this event loop as needing state restore.enqueueStateRestore(target);accumulateTwoPhaseDispatches(event);return event; }这个函数就是具体生成这个事件的一个过程 可以看到这个事件接收了一个 inst然后传入了 nativeEvent并且再传入 target然后通过 SyntheticEvent.getPooled就是说在react当中所有的事件对象是通过一个 pool 来进行一个存储的比如说我们为所有的event创建了十个event对象每一次有新的一个event进来的时候从这个pool里面拿出一个设置一些事件以及对应的一些值之后去触发每一个事件的监听方法然后去使用这个 event 对象这个 event 对象使用完了之后又会归还到这个 pool 里面也就是一个 能够减少 对象声明 以及 对象回收 的一个性能开销然后拿到了这个 event 之后给它设置了 type 是 change之后执行两个函数 enqueueStateRestore 和 accumulateTwoPhaseDispatches 进入 SyntheticEvent.getPooled// packages/events/SyntheticEvent.js#L335 function addEventPoolingTo(EventConstructor) {EventConstructor.eventPool [];EventConstructor.getPooled getPooledEvent; // 注意这里EventConstructor.release releasePooledEvent; }进入 getPooledEvent// packages/events/SyntheticEvent.js#L300 function getPooledEvent(dispatchConfig, targetInst, nativeEvent, nativeInst) {const EventConstructor this;// 存在pollif (EventConstructor.eventPool.length) {const instance EventConstructor.eventPool.pop();EventConstructor.call(instance,dispatchConfig,targetInst,nativeEvent,nativeInst,);return instance;}// pool 里面没有则创建一个新的return new EventConstructor(dispatchConfig,targetInst,nativeEvent,nativeInst,); }关于 EventConstructor 首先在 packages/events/SyntheticEvent.js#L62 中的 SyntheticEvent 构造方法要理解这个过程, 首先在这个js里面先声明了一个叫做 SyntheticEvent 这么一个方法这个方法它是一个constructor 方法, 在这个方法里面去声明事件相关的各种属性重点关注它的事件的一个触发的过程以及生产的过程所以只关心它的 pool 的处理过程 这里的 this 就是 SyntheticEvent 在这个构造方法的原型链上也有一大堆的东西对事件对象进行一个封装和扩展 注意这里的 EventConstructor.call 和 new EventConstructor 都达到同一个目的 进入 enqueueStateRestoreexport function enqueueStateRestore(target: EventTarget): void {// 判断了这个 restoreTarget 公共变量是否存在if (restoreTarget) {if (restoreQueue) {restoreQueue.push(target);} else {restoreQueue [target];}// restoreTarget 不存在则对其进行赋值} else {restoreTarget target;} }作用是处理如果setState之后这个 state 对应的 input 的 value 是不一样的要把这个值进行一个回滚 进入 accumulateTwoPhaseDispatches 这个方法才是真正要去从每个节点上面去获取它的 listener 的一个过程// packages/events/EventPropagators.js#L115 export function accumulateTwoPhaseDispatches(events) {// 其实就是对 events 这个数组里面它的每一个节点去调用这个方法forEachAccumulated(events, accumulateTwoPhaseDispatchesSingle); }function accumulateTwoPhaseDispatchesSingle(event) {// 存在 phasedRegistrationNames 则调用 traverseTwoPhaseif (event event.dispatchConfig.phasedRegistrationNames) {traverseTwoPhase(event._targetInst, accumulateDirectionalDispatches, event);} }// 在 event 对象上 插入 listener 的过程 function accumulateDirectionalDispatches(inst, phase, event) {// 忽略if (__DEV__) {warningWithoutStack(inst, Dispatching inst must not be null);}// 获取 listenerconst listener listenerAtPhase(inst, event, phase);if (listener) {// 注意这里 event._dispatchListeners 和 下面的 event._dispatchInstances 保持两者一一对应的关系event._dispatchListeners accumulateInto(event._dispatchListeners,listener,);event._dispatchInstances accumulateInto(event._dispatchInstances, inst);} }function listenerAtPhase(inst, event, propagationPhase: PropagationPhases) {const registrationName event.dispatchConfig.phasedRegistrationNames[propagationPhase];return getListener(inst, registrationName); }// packages/events/EventPluginHub.js#L126 export function getListener(inst: Fiber, registrationName: string) {let listener;// TODO: shouldPreventMouseEvent is DOM-specific and definitely should not// live here; needs to be moved to a better place soonconst stateNode inst.stateNode;if (!stateNode) {// Work in progress (ex: onload events in incremental mode).return null;}const props getFiberCurrentPropsFromNode(stateNode); // 从 dom tree上获取 propsif (!props) {// Work in progress.return null;}listener props[registrationName];if (shouldPreventMouseEvent(registrationName, inst.type, props)) {return null;}invariant(!listener || typeof listener function,Expected %s listener to be a function, instead got a value of %s type.,registrationName,typeof listener,);return listener; }// packages/shared/ReactTreeTraversal.js#L86 export function traverseTwoPhase(inst, fn, arg) {const path [];// 找到所有上层节点并存入 pathwhile (inst) {path.push(inst);inst getParent(inst);}// 下面是核心执行两个阶段的回调捕获和冒泡let i;for (i path.length; i-- 0; ) { // 注意这个 i 的顺序// path[i]节点 argeventfn(path[i], captured, arg); // captured 是从 window 向下触发的}for (i 0; i path.length; i) { // 注意这个 i 的顺序fn(path[i], bubbled, arg); // bubbled 是从下向 window 方向的}// 基于上面两个 循环// 这样的话就不需要在 event 对象上面单独维护 capture 的这个事件的它的一个数组// 还有 bubble 的事件的一个速度只需要放在同一个数组里面然后按照这个数组的顺序去触发就可以了 } // packages/shared/ReactTreeTraversal.js#L10 function getParent(inst) {do {inst inst.return;// TODO: If this is a HostRoot we might want to bail out.// That is depending on if we want nested subtrees (layers) to bubble// events to their parent. We could also go through parentNode on the// host node but that wouldnt work for React Native and doesnt let us// do the portal feature.} while (inst inst.tag ! HostComponent);if (inst) {return inst; // 返回的 inst 是一个 HostComponent}return null; }以上生产 event 对象然后去挂载它的事件这个过程是非常的复杂的 react 团队把整个事件系统去重新抽象的这么一个过程而且设计的超级复杂 这一套东西只是非常适合react在其他框架要使用这类event库会有很大的成本 目前为止通过 ChangeEventPlugin 来了解了整个 event 对象的处理过程 后续其他的类似事件的处理逻辑到后面都是一样的 但每一个 plugin 或多或少有一些自己的一些区别这里不再赘述

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

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

相关文章

做机械产品用什么网站地产项目网站

随着仓储物流和电商行业的快速发展,自动化立库设备的技术不断完善。“货到人”拣选技术越来越受到行业的重视,且已逐渐成为供需双方关注的焦点。“货到人”拣选系统主要由储存系统,补货系统,输送系统,拣选系统和包装系…

wordpress创建网站赚钱

1. 引言上两节我们通过简单的demo学习了docker的基本操作。这一节我们来一个进阶学习,完成ASP.NET Core MySql Nginx的容器化部署。本文是基于CentOS 7.4环境进行演示,示例项目可以访问Docker.NetCore.MySql进行下载。2. Hello MySQL同样我们还是以循序…

局域网建设网站如何访问北京知名网站推广

快照器管理容器文件系统的快照。 可通过运行 ctr plugins ls 或 nerdctl info 查看可用的快照器。 核心快照器插件 通用: overlayfs(默认): OverlayFS. 该驱动程序类似于 Docker/Moby 的 "overlay2 "存储驱动程序&a…

枣庄住房和城乡建设厅网站网站文件下载系统

跨域 什么是跨域?非同源限制跨域解决方案CORSJSONP服务器进行第三方代理webscoketwindow.postMessage 什么是跨域? 同源策略:协议相同、域名相同、端口号相同 的两个页面被认为是同源。 由一个页面的 js 访问不同源的页面内容,被…

网站建设公司 壹宇网络定制网站制作

概述 在工作中,软件、代码、程序这三个词经常被换用,大部分情况下,这种混用都不会出问题,实际上,它们是不同的概念,有相交的部分,也有不同的地方。本文就简单阐述一下他们的区别。 在计算机领…

ps做的网站首页vps 网站权限

ASP.NET MVC 引入了 ModelBinder 技术,让我们可以在 Action 中以强类型参数的形式接收 Request 中的数据,极大的方便了我们的编程,提高了生产力。在查询 Action 中,我们可以将 Expression Trees 用作参数,通过自定义的…

网站知识架构腾讯云做wordpress太卡

视频链接: 视频 代码链接: 源码 在C#中,静态类(Static Class)和静态方法(Static Method)是面向对象编程中的重要概念。它们允许你创建不依赖于对象实例的方法和属性,而是直接通过类名来访问。 静态类 静…

营销网站制作企业虚拟主机网站建设步骤?

原文作者:心莱科技肖鑫简单来说机器学习的核心步骤在于“获取学习数据;选择机器算法;定型模型;评估模型,预测模型结果”,下面本人就以判断日报内容是否合格为例为大家简单的阐述一下C#的机器学习。第一步&a…

企业网站如何设计网页网站建设报价表模板

Python遥感开发之批量拼接 1 遥感图像无交错的批量拼接2 遥感图像有交错的批量拼接 前言:主要借助python实现遥感影像的批量拼接,遥感影像的批量拼接主要分为两种情况,一种是遥感图像无交错,另一种情况是遥感图像相互有交错。具体…

电子商务网站建设和运营1688阿里巴巴官网

全世界只有3.14 % 的人关注了爆炸吧知识首先来看你绝对干过的15件傻事儿,别不承认!把树叶弄成这样喝酸奶舔盖子吃完棒冰继续含着棍子咬拉链尝试用笔写一首歌比如《生日快乐》对着电风扇说话或喊叫刮墙壁上的油漆过斑马线只踩白色部分猫打哈欠时伸手指进去…

网页内容沧州网站优化

数据类型之Integer与int Java入门 基本数据类型 众所周知,Java是面向对象的语言,一切皆对象。但是为了兼容人类根深蒂固的数据处理习惯,加快常规数据的处理速度,提供了9种基本数据类型,他们都不具备对象的特性&#xf…

国内网站设计公司做网站是58好还是百度好

在HTML中&#xff0c;如果你想动态设置下拉选项&#xff08;<select>元素中的<option>&#xff09;&#xff0c;你可以使用JavaScript。以下是一个示例&#xff0c;展示了如何使用JavaScript来动态添加下拉选项&#xff1a; <!DOCTYPE html> <…

企业门户网站建设管理制度网站如何设置域名

目录 基本介绍 安装添加模块 模块配置指令 基本介绍 nginx的memcached_module模块可以直接从memcached服务器中读取内容后输出&#xff0c;后续的请求不再经过应用程序处理&#xff0c;如php-fpm、django&#xff0c;大大的提升动态页面的速度。nginx只负责从memcach…

wordpress关闭多站点网站的站点的管理系统

跟着施磊老师做C项目&#xff0c;施磊老师_腾讯课堂 (qq.com) 一、基于muduo网络库开发服务器程序 组合TcpServer对象创建EventLoop事件循环对象的指针明确TcpServer构造函数需要什么参数,输出ChatServer的构造函数在当前服务器类的构造函数当中,注册处理连接的回调函数和处理…

网站设计排版怎么做长沙seo网站管理

每天五分钟分享一个电商模式&#xff0c;大家好我是商业模式策划啊浩。 今天给大家分享的模式叫作“二二复制”&#xff0c;我有一个客户通过我给他设计的这套模式实现销量破千万&#xff0c;大家如果对此感兴趣的话把自己的问题记录下来&#xff0c;看完文章后留言到评论区&am…

莱芜最好的网站建设公司wordpress 页面 插件

Github分支开发&#xff1a; 第1步&#xff1a;在github上创建一个新的dev分支&#xff1a; 更新了微信的PC版本&#xff0c;发现默认的箭头比以前加粗了&#xff0c;变得更好看了。 create branch: dev from master。 切换到该分支&#xff0c;看到里面的内容跟master分支的…

国内优秀网站网址怎样进行文化建设

文章主题&#xff1a;复杂度详解&#x1f331;所属专栏&#xff1a;深入理解数据结构&#x1f4d8;作者简介&#xff1a;更新有关深入理解数据结构知识的博主一枚&#xff0c;记录分享自己对数据结构的深入解读。&#x1f604;个人主页&#xff1a;[₽]的个人主页&#x1f525;…

网站整站模板江西网站建设

【C语言】——指针七&#xff1a; 前言一、 s i z e o f sizeof sizeof 与 s t r l e n strlen strlen 的对比1.1、 s i z e o f sizeof sizeof1.2、 s t r l e n strlen strlen1.3、 s i z e o f sizeof sizeof 和 s t r l e n strlen strlen 对比 二、数组和指针笔试题解析…

汝州市住房和城乡建设局网站小程序源码教程

free &#xff1a;观察内存使用情况 系统当中有 2848MB 左右的实体内存&#xff0c;我的 swap 有 1GB 左右&#xff0c; 那我使用free -m 以 MBytes 来显示时&#xff0c;就会出现上面的信息。Mem 那一行显示的是实体内存的量&#xff0c;Swap 则是内存交换空间的量。 total 是…

数据网站建设成本山东省住房城乡建设部网站

试卷代号&#xff1a;1260 软件工程 试题&#xff08;半开卷&#xff09; 2019年7月 一、选择题&#xff0c;请从四个可选项中选择正确答案。&#xff08;60分&#xff0c;每题3分&#xff09; 1.以下哪一项不是软件危机的表现形式&#xff08; &#xff09;。 A.成本高 B.生产…