范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

ReactHooks的原理,有的简单有的不简单

  React 是实现了组件的前端框架,它支持 class 和 function 两种形式的组件。
  class 组件是通过继承模版类(Component、PureComponent)的方式开发新组件的,继承是 class 本身的特性,它支持设置 state,会在 state 改变后重新渲染,可以重写一些父类的方法,这些方法会在 React 组件渲染的不同阶段调用,叫做生命周期函数。
  function 组件不能做继承,因为 function 本来就没这个特性,所以是提供了一些 api 供函数使用,这些 api 会在内部的一个数据结构上挂载一些函数和值,并执行相应的逻辑,通过这种方式实现了 state 和类似 class 组件的生命周期函数的功能,这种 api 就叫做 hooks。
  hooks 挂载数据的数据结构叫做 fiber。
  那什么是 fiber 呢?
  我们知道,React 是通过 jsx 来描述界面结构的,会把 jsx 编译成 render function,然后执行 render function 产生 vdom:
  图片
  在 v16 之前的 React 里,是直接递归遍历 vdom,通过 dom api 增删改 dom 的方式来渲染的。但当 vdom 过大,频繁调用 dom api 会比较耗时,而且递归又不能打断,所以有性能问题。
  图片
  后来就引入了 fiber 架构,先把 vdom 树转成 fiber 链表,然后再渲染 fiber。
  图片
  vdom 转 fiber 的过程叫做 reconcile,是可打断的,React 加入了 schedule 的机制在空闲时调度 reconcile,reconcile 的过程中会做 diff,打上增删改的标记(effectTag),并把对应的 dom 创建好。然后就可以一次性把 fiber 渲染到 dom,也就是 commit。
  这个 schdule、reconcile、commit 的流程就是 fiber 架构。当然,对应的这个数据结构也叫 fiber。
  (更多 fiber 的介绍可以看我之前的一篇文章:手写简易版 React 来彻底搞懂 fiber 架构)
  hooks 就是通过把数据挂载到组件对应的 fiber 节点上来实现的。
  fiber 节点是一个对象,hooks 把数据挂载在哪个属性呢?
  我们可以 debugger 看下。
  准备这样一个函数组件(代码没啥具体含义,就是为了调试 hooks):
  function App() {
  const [name, setName] = useState("guang");
  useState("dong");
  const handler = useCallback((evt) => {
  setName("dong");
  },[1]);
  useEffect(() => {
  console.log(1);
  });
  useRef(1);
  useMemo(() => {
  return "guang and dong";
  })
  return (
  {name}
  
  );
  }
  在函数打个断点,运行到这个组件就会断住。
  我们看下调用栈:
  图片
  上一个函数是 renderWithHooks,里面有个 workingInProgress 的对象就是当前的 fiber 节点:
  图片
  fiber 节点的 memorizedState 就是保存 hooks 数据的地方。
  它是一个通过 next 串联的链表,展开看一下:
  图片
  链表一共六个元素,这和我们在 function 组件写的 hooks 不就对上了么:
  图片
  这就是 hooks 存取数据的地方,执行的时候各自在自己的那个 memorizedState 上存取数据,完成各种逻辑,这就是 hooks 的原理。
  这个 memorizedState 链表是什么时候创建的呢?
  好问题,确实有个链表创建的过程,也就是 mountXxx。链表只需要创建一次,后面只需要 update。
  所以第一次调用 useState 会执行 mountState,后面再调用 useState 会执行 updateState。
  图片
  图片
  我们先集中精力把 mount 搞明白。
  mountXxx 是创建 memorizedState 链表的过程,每个 hooks api 都是这样的:
  图片
  图片
  图片
  它的实现也很容易想到,就是创建对应的 memorizedState 对象,然后用 next 串联起来,也就是这段代码:
  图片
  当然,创建这样的数据结构还是为了使用的,每种 hooks api 都有不同的使用这些 memorizedState 数据的逻辑,有的比较简单,比如 useRef、useCallback、useMemo,有的没那么简单,比如 useState、useEffect。
  为什么这么说呢?我们看下它们的实现再说吧。
  先看这几个简单的:
  useRef
  每个 useXxx 的 hooks 都有 mountXxx 和 updateXxx 两个阶段,比如 ref 就是 mountRef 和 updateRef。
  它的代码是最简单的,只有这么几行:
  图片
  mountWorkInProgressHook 刚才我们看过,就是创建并返回 memorizedState 链表的,同理,下面那个 updateWorkInProgressHook 是更新的。
  这些不用管,只要知道修改的是对应的 memorizedState 链表中的元素就行了。
  那 ref 在 memorizedState 上挂了什么呢?
  可以看到是把传进来的 value 包装了一个有 current 属性的对象,冻结了一下,然后放在 memorizedState 属性上。
  后面 update 的时候,没有做任何处理,直接返回这个对象。
  所以,useRef 的功能就很容易猜到了:useRef 可以保存一个数据的引用,这个引用不可变。
  这个 hooks 是最简单的 hooks 了,给我们一个地方存数据,我们也能轻易的实现 useRef 这个 hooks。
  再来看个稍难点的:
  useCallback
  useCallback 在 memorizedState 上放了一个数组,第一个元素是传入的回调函数,第二个是传入的 deps(对 deps 做了下 undefined 的处理)。
  图片
  更新的时候把之前的那个 memorizedState 取出来,和新传入的 deps 做下对比,如果没变,那就返回之前的回调函数,也就是 prevState[0]。
  如果变了,那就创建一个新的数组,第一个元素是传入的回调函数,第二个是传入的 deps。
  所以,useCallback 的功能也就呼之欲出了:useCallback 可以实现函数的缓存,如果 deps 没变就不会创建新的,否则才会返回新传入的函数。
  这段逻辑其实也不难,就是多了个判断逻辑。
  再来看个和它差不多的:
  useMemo
  useMemo 也在 memorizedState 上放了个数组,第一个元素是传入函数的执行结果,第二个元素是 deps(对 deps 为 undefined 的情况做了下处理)。
  图片
  更新的时候也是取出之前的 memorizedState,和新传入的 deps 做下对比,如果没变,就返回之前的值,也就是 prevState[0]。
  如果变了,创建一个新的数组放在 memorizedState,第一个元素是新传入函数的执行结果,第二个元素是 deps。
  所以,useMemo 的功能大家也能猜出来:useMemo 可以实现函数执行结果的缓存,如果 deps 没变,就直接拿之前的,否则才会执行函数拿到最新结果返回。
  实现逻辑和 useCallback 大同小异。
  这三个 hooks 难么?给大家一个对象来存储数据,大家都能写出来,并不难。
  因为它们是没有别的依赖的,只是单纯的缓存了下值而已。而像 useState、useEffect 这些就复杂一些了,主要是因为需要调度。
  useState
  state 改了之后是要触发更新的调度的,React 有自己的调度逻辑,就是我们前面提到的 fiber 的 schedule,所以需要 dispatch 一个 action。
  (不展开讲,简单看一下)
  图片
  这里详细讲要涉及到调度,就先不展开了。
  useEffect
  同样的,effect 传入的函数也是被 React 所调度的,当然,这里的调度不是 fiber 那个调度,而是单独的 effect 调度:
  (不展开讲,简单看一下)
  图片
  hooks 负责把这些 effect 串联成一个 updateQueue 的链表,然后让 React 去调度执行。
  图片
  所以说,useState、useEffect 这种 hooks 的实现是和 fiber 的空闲调度,effect 的调度结合比较紧密的,实现上更复杂了一些。
  这里没有展开讲,因为这篇文章的目的是把 hooks 的主要原理理清楚,不会太深入细节。
  大家可能还听过自定义 hooks 的概念,那个是啥呢?
  其实就是个函数调用,没啥神奇的,我们可以把上面的 hooks 放到 xxx 函数里,然后在 function 组件里调用,对应的 hook 链表是一样的。
  图片
  只不过一般我们会使用 React 提供的 eslint 插件,lint 了这些函数必须以 use 开头,但其实不用也没事,它们和普通的函数封装没有任何区别。
  总结
  React 支持 class 和 function 两种形式的组件,class 支持 state 属性和生命周期方法,而 function 组件也通过 hooks api 实现了类似的功能。
  fiber 架构是 React 在 16 以后引入的,之前是 jsx -> render function -> vdom 然后直接递归渲染 vdom,现在则是多了一步 vdom 转 fiber 的 reconcile,在 reconcile 的过程中创建 dom 和做 diff 并打上增删改的 effectTag,然后一次性 commit。这个 reconcile 是可被打断的,可以调度,也就是 fiber 的 schedule。
  hooks 的实现就是基于 fiber 的,会在 fiber 节点上放一个链表,每个节点的 memorizedState 属性上存放了对应的数据,然后不同的 hooks api 使用对应的数据来完成不同的功能。
  链表自然有个创建阶段,也就是 mountXxx,之后就不需要再 mount 了,只需要 update。所以每个 useXx 的实现其实都是分为了 mountXxx 和 updateXxx 两部分的。
  我们看了几个简单的 hooks:useRef、useCallback、useMemo,它们只是对值做了缓存,逻辑比较纯粹,没有依赖 React 的调度。而 useState 会触发 fiber 的 schedule,useEffect 也有自己的调度逻辑。实现上相对复杂一些,我们没有继续深入。
  其实给我们一个对象来存取数据,实现 useRef、useCallback、useMemo 等 hooks 还是很简单的。对于需要调度的,则复杂一些。
  对于自定义的 hooks,那个就是个函数调用,没有任何区别。(lint 的规则不想遵守可以忽略)
  所有 hooks api 都是基于 fiber 节点上的 memorizedState 链表来存取数据并完成各自的逻辑的。
  所以,hooks 的原理简单么?只能说有的简单,有的不简单。

vivo蔡司影像展上海站以专业致敬专业,回忆影像故事vivo去年和蔡司联合定制了vivoX60系列的摄像头方案,从蔡司色彩到蔡司T镀膜,vivo用vivoX60系列在手机影像中掀起了一股浪潮。今日,vivo携手全球知名影像光学品牌蔡联想美好假期温暖2021,总有一个故事会打动你这是2021年第一份套餐A,2021年我们还会将套餐A活动继续做下去,继续将爱心传递下去,在济南街头,玖壹粉面馆老板对于联想美好假期志愿者们的到来,既惊喜又意外。(套餐A的内容)其女儿为何更喜欢爸爸,难道真的是上辈子的情人?白苏说文经常听别人说女儿是爸爸前世的情人。以前还没怎么体会到这种感觉,直到女儿两岁,我才稍微有一点点体会,不过小家伙给我的感觉很纯粹,很特别她那么小,对待爸爸和妈妈竟然完全不一样,550T版新增48V轻混系统2022款雪佛兰探界者上市配置升级日前,上汽通用雪佛兰官方宣布,旗下的2022款探界者车型上市,新车推出6款车型可选,官方指导价区间为16。99万元23。99万元。作为年度改款车型,新车在外形方面并无调整,前脸依然显卡价格高涨是做等等党还是先行入手?这个答案也许会有启发自打进入三月中旬以后,显卡的价格依然没有掉头向下的迹象,相反的是随着RTX3060密算限制解除驱动的意外挂出,导致玩家的希望RTX3060也一路水涨船高。现在的显卡市场状况如何呢?元宇宙第一股Roblox在停机三天后重新上线编译VR陀螺Roblox在持续三天的大停机后于美国东部时间周日恢复了服务。Roblox是一个允许用户玩和创建游戏的在线平台,它在美国东部时间10月28日星期四晚上7点左右开始出现问Admix获2500万美元B轮融资,正通过InPlay实现元宇宙货币化编译VR陀螺本周,专门为VRAR开发者提供程序化广告解决方案的Admix公司宣布完成2500万美元B轮融资。本轮融资由Elefund与DIPCapital领投,ForceOverM元宇宙前所未有的真实可触从NVIDIASIGGRAPH造假纪录片谈起所谓元宇宙(Metaverse),其实是虚拟现实世界的另一种称呼,有时候特指的是融入了社交功能的三维游戏,2018年的电影头号玩家(PlayerOne)里的游戏就是元宇宙的一种表现咪咕发布元宇宙MIGU演进路线图,将通过5GMSC,打造体育元宇宙VR陀螺11月3日讯,11月2日下午,以云上精彩,共创数智生活为主题的2021中国移动全球合作伙伴大会产品创新融合发布会在广州召开。中国移动咪咕公司总经理刘昕以搭乘5G信息高铁加速命名奇骏经典?老款日产奇骏有望复产缓解销量危机据国内媒体报道,日产旗下的老款奇骏车型有望复产,未来会命名为经典版奇骏,和全新奇骏同堂销售。配图为2020款奇骏老款车型复产的原因显然和全新一代奇骏销量表现不算给力有关系,从乘联会国产机械键盘推荐,谁是你心中的国货之光呢?机械键盘的市场愈发成熟,各种各样的产品层出不穷,大众或被动或主动地对机械键盘也有了更深的了解。而外设领域中国外品牌一直占主导地位,但是近几年,有许多国产品牌因为精湛的工艺和过硬的质
我国的基建现在是否依旧有发展前景?政信里还是很火热?主要是来自于政府牵头,然后政信投资集团帮助筹集资金,一方面政府会有比较优质的项目,比如5G的建设,各种公路的打通修建等等,都是关乎民生的工程另一方面还会有政信投资集团这样的机构去把苹果手机有什么小功能?1编写短信的时候,如果想把写的内容全删掉,只需晃动你的iPhone几下,会弹出个窗口,选择撤销键入就可把内容全删掉了,不用按着删除键半天。如果想把刚删掉的内容恢复,晃动iPhone科技部共有212项技术在北京冬奥会上落地应用央广网北京2月16日消息16日,在2022北京新闻中心新闻发布会科技冬奥有关情况专场上,科技部社发司司长祝学华介绍,2016年,在北京冬奥组委统筹协调下,科技部会同国家体育总局北京炒作or趋势?从TheSandboxDecentraland等头部项目探讨元宇宙发展近期,元宇宙可谓是圈内圈外人都会提及的一项话题,每个人对元宇宙都有一些自己的思考。扎克伯格认为,在元宇宙里面,你感觉与其他人一起,就如现实中的跳舞健身一样,不同的在于这种体验是不能适合18岁左右男孩子用的手机有哪些?我也是名18岁的大学生,我认为大学生家境一般的话就选择2000以下的手机就够了够你用个一两年的。手机更新换代速度太快。科技发展也迅速,买新不买旧下面几款都是我比较喜欢的颜值高(我买5小时工作2分钟搞定!AIOps带你飞来源计算机世界在上两篇微信有了AI,IT运维原来可以这么轻松和80用过的企业都获得了回报!AIOps到底强在哪儿?中,我们认识了AIOps和它的妙用,那它在企业中的实际应用又如何呢一身债务他通过当外卖员还清,还当上小队长,给平台提建议被采纳外卖骑手伴随着外卖行业的发展而诞生,他们穿梭在城市之间,支撑起如今的到家经济。他们不仅有了属于自己的新职业名称网约配送员,也有了一份能稳定的工作,这份工作更成为他们有希望的职业发展路由器在客厅,卧室没信号怎么办?换路由器呗中兴AX5400PRO体验hello大家好,这里是你们一直悄咪咪捡垃圾不写却一直写NAS的晋升奶爸的垃圾佬。引子前几天小伙伴找奶爸来问我家路由器在客厅,一个卧室始终没有WiFi信号,该买个啥牌子的路由器?奶京拼多多店铺常见会被处罚的三种情况和解决这三个被处罚的方法京东商家应用接口拼多多店铺常见会被处罚的三种情况和解决这三个被处罚的方法有些做电商的朋友和我说,没被罚过都不算做过拼多多!还有一个刚刚开店一个月的朋友吐槽,货没卖出几件,钱到罚的不从落地开花到触手可及人工智能正迎来绽放时刻来源人民邮电报在第24届冬奥会开幕式的主题曲演唱环节,几百个孩子手举发光的和平鸽在鸟巢中央奔跑,孩子们脚下的屏幕随即亮起雪花这其实是人工智能的0延时捕捉和平鸽技术在大放异彩,是在大如果未来出现了一座人口破亿的城市,那会是哪一座城市?我是头条号贺千城财经的作者,我来回答。未来会出现一座人口破亿的城市,这真是一件很有想象力的事情啊!至于会不会出现,我认为发生的概率只有1,也绝不会出现。新德里现在,中国和印度是全球