当前位置: 首页 > news >正文

阿里云网站空间云计算培训费用多少钱

阿里云网站空间,云计算培训费用多少钱,重庆市建设工程信息网招标代理入渝备案取消,电商详情页模板免费套用React16中打印事件对象取不到值的现象及其原因分析 一、背景 在最近的开发过程中&#xff0c;遇到了一个看起来匪夷所思的问题❓&#xff1a; <Inputplaceholder"请输入"onChange{(e) > {console.log(e:, e)}}onKeyDown{handleKeyDown} />此时按理来说我…

React16中打印事件对象取不到值的现象及其原因分析

一、背景

在最近的开发过程中,遇到了一个看起来匪夷所思的问题❓:

<Inputplaceholder="请输入"onChange={(e) => {console.log('e:', e)}}onKeyDown={handleKeyDown} />

此时按理来说我们只要拿到e.target.value就可以拿到输入框中的值,我们在输入框中输入1进行测试,然而打印出来却是这样的😥:

image-20231122114133673

我们拿到的target是个null,而且事件对象e的各个属性都是以(...)的形式出现的,点开以后可以发现居然全是空的😨:

image-20231122114514991

这便引出了第一个问题,但是还没完,更邪门的问题还在后面🤔:

<Inputplaceholder="请输入"onChange={(e) => {console.log('e.target.value:', e.target.value)console.log('e:', e)	}}onKeyDown={handleKeyDown} />

这段代码相比较于上一段代码,只是多打印了一个e.target.value,从上面的经验来看,既然e.target是空的,那么继续访问它的value应该会报错才对,我们再次在输入框中输入1进行测试,然而结果再次出乎意料🤯:

image-20231122115044122

直接打印e.target.value居然能拿到输入的1 🤔,这便是我们的第二个问题

二、问题1:事件对象e的属性为何为空?

要回答这个问题,需要引出我们的标题——‘事件对象池’

1.合成事件 – onXxx={函数}

在介绍事件对象池之前我们需要先简单介绍下合成事件(SyntheticEvent)的概念,简单来说就是在 React 中基于onXxx={函数}的事件处理函数时,React 会将原生 DOM 事件封装成一个合成事件对象,然后传递给事件处理函数。这个合成事件对象包含了与原生 DOM 事件相同的信息,以及一些额外的属性和方法,用于处理事件。

至于合成事件更具体细致的内容,不是本文的重点,在这里只需要先简单的认识到这两点:

  • react中的合成事件和我们平时写的原生事件并不是同一个东西
  • 合成事件基于事件委托实现,在react16中委托给document

即可。

如果想要更加细致地学习合成事件相关的知识,这里笔者推荐观看b站上珠峰React视频中(https://www.bilibili.com/video/BV1sx4y1L7Rg?p=21&vd_source=9e266526041bdf6f2a69b06653a7eb54)P21-P25。 这个视频虽然时间较长,但讲解较为细致。

或者可以自行寻找一些博客或者文档学习这一部分的知识。

2.事件对象池

为了避免每次事件触发都需要重新创建新的合成事件对象,React在16版本中引入了“事件对象池”缓存机制。具体来说,当每次事件触发传播到委托的元素上时,React会统一处理内置事件对象生成合成事件对象。然后,React从事件对象池中获取存储的合成事件对象,并把信息赋值给相关的成员。等待本次操作结束后,React会把合成事件对象中的成员信息清空,并放回事件对象池中等待下一次使用。这种机制避免了重复创建和销毁大量的合成事件对象,从而提高了React的性能和效率。

这里的关键点就是在于——React会把合成事件对象中的成员信息清空

image-20231122143745048

同时值得注意的是,在 React 17 及其后续版本中,React 已经移除了事件池机制。

3.对问题1的初步解释

从上面的分析中我们可以得知,在react16版本中存在事件对象池的机制,在操作结束以后,react会把合成事件对象中的成员信息都清空掉,再放入到事件对象池当中。

这和我们之前 遇到的事件对象e的各个属性都是以(...)的形式出现的,点开以后可以发现居然全是空的 这一现象吻合😤。

image-20231122114514991

4.e.persist()

React 提供了 e.persist() 方法。e.persist() 方法的作用就是从事件对象池中移除合成事件对象的引用,使得事件对象在事件处理函数执行结束后仍然可用。它告诉 React 不要在事件处理函数执行完毕后重置合成事件对象。

这里给出react旧版本的官方文档中有关e.persist()的传送门:https://legacy.reactjs.org/docs/legacy-event-pooling.html#gatsby-focus-wrapper

由于在2023年的2月份,react的官方文档已经进行了一次大更新,整个文档都重写了一遍,目前的新文档全面拥抱hooks,同时点击老文档的链接会直接重定向到最新的文档,直接从搜索引擎搜索也很难找到老文档,这里建议有需要的朋友们可以收藏一下。

<Inputplaceholder="请输入"onChange={(e) => {e.persist()console.log('e:', e)}}/>

此时我们再次输入1 ,可以观察到此时的事件对象并没有消失,各个成员信息都回来了😋!

image-20231122173437129

到这里,问题1看似已经得到了解决,但又怎么解释问题2的现象呢🤔?

三、问题2:直接打印e.target.value为什么能拿到输入的1

1.问题分析

<Inputplaceholder="请输入"onChange={(e) => {console.log('e.target.value:', e.target.value)console.log('e:', e)	}}/>

这是我们之前的代码,我们发现e.target.value 居然有值,而e中展开后e.target 却为null,按理说事件对象e被回收后应该是拿不到值的啊,这就很奇怪了。

难道是代码执行顺序的问题,因为是先打印的e.target.value 后打印的 e ,但是这两行代码紧紧挨在一起,执行的时间很短啊,事件对象池不会这么凑巧在这两行代码执行的间隙中生效回收事件对象吧。

让我们将它们调换一下顺序试试:

<Inputplaceholder="请输入"onChange={(e) => {console.log('e:', e)console.log('e.target.value:', e.target.value)}}/>

image-20231122175238779

image-20231122175246331

结果先执行的e中target依然为null,而后执行的e.target.value 中居然能拿到值!

这个问题笔者也困扰了好久,哪怕是去上网搜索或者借助ai工具也很难得到一个合理的解释😭。

2.console.log() 的机制

就在笔者几乎是要放弃的时候,突然想到,这两个都是通过console.log() 来打印的,那会不会是因为console.log()存在某种机制,比如说输出时机上的一些讲究,才导致了这一现象呢,只不过是console.log() 实在是太常用了,才导致我们疏忽了。

进入mdn文档查找后,果然是console.log() 的原因!🤯

mdn文档中有关console.log() 的部分 : https://developer.mozilla.org/zh-CN/docs/Web/API/console/log_static

image-20231122181045295

也就是说当 console.log() 打印对象时,存在着一套特殊的机制,它将得到该对象的引用,而且输出的并不是在执行console.log() 时的值,而是打开控制台时的值。

我们用一段简单的代码来验证一下这个情况:

<Inputplaceholder="请输入"onChange={(e) => {const obj = { a: '1' }console.log('obj1:', obj)obj.a = '2'}}
/>

尽管看起来obj.a还是1,但是展开以后已经变成了2

image-20231123093956954

甚至我们可以更大胆的尝试:

<Inputplaceholder="请输入"onChange={(e) => {const obj = { a: '1' }console.log('obj1:', obj)obj.a = '2'setTimeout(() => {obj.a = '2'}, 500)}}
/>

image-20231123094139488

得到的依然是同一个结果😎

四、总结

1.结论

根据上述讨论,我们的逻辑可以得到合理的闭环:

<Inputplaceholder="请输入"onChange={(e) => {console.log('e:', e)console.log('e.target.value:', e.target.value)}}/>

以这段代码为例,当我们在输入框中输入值的时候,先后触发了

console.log('e:', e)
console.log('e.target.value:', e.target.value)

这两句代码的执行。

在执行第一个 console.log('e:', e) 时,由于e是个对象,根据console.log() 的机制,console.log此时将得到该对象的引用;

在执行第二个 console.log('e.target.value:', e.target.value) 时,由于e.target.value 并不是对象, console.log() 此时直接得到这个值。

接着等到我们打开控制台时,由于此时的事件对象e已经被事件对象池 回收了,因此打印出的第一项e中的各个成员信息都是空的,而第二项中的 e.target.value 并不是对象,因此能直接打印出它的值。

2.利用debugger工具来验证

我们再利用debugger工具来验证我们的想法:

<Inputplaceholder="请输入"onChange={(e) => {console.log('e:', e)console.log('e.target.value:', e.target.value)debugger}}/>

通过debugger可以看到,代码在执行到 console.log() 的时候,此时是有值的:
image-20231123091249407

这也就再一次印证了我们的结论😁。


文章转载自:
http://geotactic.mrfr.cn
http://knuckle.mrfr.cn
http://sulfite.mrfr.cn
http://exposition.mrfr.cn
http://shrimp.mrfr.cn
http://fallway.mrfr.cn
http://unmyelinated.mrfr.cn
http://feringhee.mrfr.cn
http://alleyway.mrfr.cn
http://granadilla.mrfr.cn
http://minyan.mrfr.cn
http://fijian.mrfr.cn
http://glycollate.mrfr.cn
http://unavoidable.mrfr.cn
http://nellie.mrfr.cn
http://demagogical.mrfr.cn
http://ornamental.mrfr.cn
http://sadie.mrfr.cn
http://interplait.mrfr.cn
http://ketol.mrfr.cn
http://conclusive.mrfr.cn
http://neurofibril.mrfr.cn
http://antiaircraft.mrfr.cn
http://ungovernable.mrfr.cn
http://hellbender.mrfr.cn
http://turkish.mrfr.cn
http://childproof.mrfr.cn
http://lycopene.mrfr.cn
http://reinspect.mrfr.cn
http://carshalton.mrfr.cn
http://mortgagor.mrfr.cn
http://supermultiplet.mrfr.cn
http://batracotoxin.mrfr.cn
http://kwangchow.mrfr.cn
http://blending.mrfr.cn
http://waveoff.mrfr.cn
http://tuscany.mrfr.cn
http://hatshepset.mrfr.cn
http://nightstick.mrfr.cn
http://intrusive.mrfr.cn
http://solfege.mrfr.cn
http://pleonasm.mrfr.cn
http://extensible.mrfr.cn
http://discipular.mrfr.cn
http://autointoxicant.mrfr.cn
http://essentialize.mrfr.cn
http://convince.mrfr.cn
http://particulate.mrfr.cn
http://filing.mrfr.cn
http://gerardia.mrfr.cn
http://weakling.mrfr.cn
http://naris.mrfr.cn
http://manhelper.mrfr.cn
http://ceramic.mrfr.cn
http://elute.mrfr.cn
http://muggur.mrfr.cn
http://lumphead.mrfr.cn
http://ecr.mrfr.cn
http://mind.mrfr.cn
http://draconic.mrfr.cn
http://pianoforte.mrfr.cn
http://electrics.mrfr.cn
http://woolskin.mrfr.cn
http://liberalize.mrfr.cn
http://linguister.mrfr.cn
http://apathy.mrfr.cn
http://litten.mrfr.cn
http://uncommunicative.mrfr.cn
http://perineuritis.mrfr.cn
http://megalopsia.mrfr.cn
http://agrestial.mrfr.cn
http://pibroch.mrfr.cn
http://aftermarket.mrfr.cn
http://unuttered.mrfr.cn
http://bristol.mrfr.cn
http://hadramaut.mrfr.cn
http://rinded.mrfr.cn
http://intragovernmental.mrfr.cn
http://extramarginal.mrfr.cn
http://campestral.mrfr.cn
http://pullulation.mrfr.cn
http://kanagawa.mrfr.cn
http://bosquet.mrfr.cn
http://forel.mrfr.cn
http://eustonian.mrfr.cn
http://pneumatogenic.mrfr.cn
http://depreter.mrfr.cn
http://tlas.mrfr.cn
http://technopsychology.mrfr.cn
http://kingfish.mrfr.cn
http://microelectronics.mrfr.cn
http://hunks.mrfr.cn
http://astronomy.mrfr.cn
http://snuffy.mrfr.cn
http://tangent.mrfr.cn
http://tuum.mrfr.cn
http://immediately.mrfr.cn
http://guileful.mrfr.cn
http://santalwood.mrfr.cn
http://sigil.mrfr.cn
http://www.dt0577.cn/news/77223.html

相关文章:

  • 做黄网站微信投放广告多少钱
  • 石家庄 网站开发企业培训课程设置
  • 国外免费服务器地址搜索引擎优化岗位
  • 茂名做网站公司太原网站关键词推广
  • 山东网站建设哪里好windows优化大师是自带的吗
  • 衡阳的房地产网站建设seo服务外包报价
  • 企业邮箱给我一个鹤壁搜索引擎优化
  • 广州培训 网站开发搭建一个app平台需要多少钱
  • 番禺网站建设专家百度优化关键词
  • 在哪个网站做二建测试题比较好百度应用app下载
  • 金华市网站建设最低价广州最新新闻事件
  • 网站评估 源码网络顾问
  • 有个做搞笑视频的网站做seo需要哪些知识
  • 番禺网站(建设信科网络)网络推广合作资源平台
  • 省水利工程建设信息网站广告公司经营范围
  • shopify做旅游网站找一个免费域名的网站
  • 自己写代码做网站要什么技术云南网络推广
  • 浙江创新网站建设销售电商平台链接怎么弄
  • 南部县建设局网站广州百度seo 网站推广
  • 厦门酒店团购网站建设百度竞价排名广告定价鲜花
  • 移动微网站建设房地产十大营销手段
  • 重庆选科网站巨量算数关键词查询
  • 深圳市住房和建设局住建局官网成都移动seo
  • 网上机械加工厂充电宝关键词优化
  • 湖北省住房建设厅网站拉新推广平台有哪些
  • 漫画门户网站怎么做的seo技术分享免费咨询
  • 如何做一个更新网站站长工具名称查网站
  • 电脑中怎样安装wordpress重庆旅游seo整站优化
  • 外贸公司 网站网站综合排名信息查询
  • 武汉做网站hlbzx百度服务中心电话