文章详情

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

请输入下面的图形验证码

提交验证

短信预约提醒成功

react怎么实现hooks

2024-04-02 19:55

关注

这篇文章主要介绍“react怎么实现hooks”,在日常操作中,相信很多人在react怎么实现hooks问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”react怎么实现hooks”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

react怎么实现hooks

React 的 hooks 是在 fiber 之后出现的特性,所以很多人误以为 hooks 是必须依赖 fiber 才能实现的,其实并不是,它们俩没啥必然联系。

现在,不止 react 中实现了 hooks,在 preact、react ssr、midway 等框架中也实现了这个特性,它们的实现就是不依赖 fiber 的。

我们分别来看一下这些不同框架中的 hooks 都是怎么实现的:

react 如何实现 hooks

react 是通过 jsx 描述界面的,它会被 babel 或 tsc 等编译工具编译成 render function,然后执行产生 vdom:

react怎么实现hooks

这里的 render function 在 React17 之前是 React.createElement:

react怎么实现hooks

在 React 17 之后换成了 jsx:

react怎么实现hooks

这个 jsx-runtime 会自动引入,不用像之前那样每个组件都要保留一个 React 的 import 才行。

render function 执行产生 vdom:

react怎么实现hooks

vdom 的结构是这样的:

react怎么实现hooks

在 React16 之前,会递归渲染这个 vdom,增删改真实 dom。

react怎么实现hooks

而在 React16 引入了 fiber 架构之后就多了一步:首先把 vdom 转成 fiber,之后再渲染 fiber。

react怎么实现hooks

vdom 转 fiber 的过程叫做 reconcile,最后增删改真实 dom 的过程叫做 commit。

为什么要做这样的转换呢?

因为 vdom 只有子节点 children 的引用,没有父节点 parent 和其他兄弟节点 sibling 的引用,这导致了要一次性递归把所有 vdom 节点渲染到 dom 才行,不可打断。

万一打断了会怎么样呢?因为没有记录父节点和兄弟节点,那只能继续处理子节点,却不能处理 vdom 的其他部分了。

所以 React 才引入了这种 fiber 的结构,也就是有父节点 return、子节点 child、兄弟节点 sibling 等引用,可以打断,因为断了再恢复也能找到后面所有没处理过的节点。

fiber 节点的结构是这样的:

react怎么实现hooks

这个过程可以打断,自然也就可以调度,也就是 schdule 的过程。

所以 fiber 架构就分为了 schdule、reconcile(vdom 转 fiber)、commit(更新到 dom)三个阶段。

函数组件内可以用 hooks 来存取一些值,这些值就是存在 fiber 节点上的。

比如这个函数组件内用到了 6 个 hook:

react怎么实现hooks

那么对应的 fiber 节点上就有个 6 个元素的 memorizedState 链表:

react怎么实现hooks

通过 next 串联起来:

react怎么实现hooks

不同的 hook 在 memorizedState 链表不同的元素上存取值,这就是 react hooks 的原理。

这个链表有创建阶段和更新阶段,所以你会发现 useXxx 的最终实现都分为了 mountXxx 和 updateXxx:

react怎么实现hooks

这里的 mount 阶段就是创建 hook 节点并组装成链表的:

react怎么实现hooks

会把创建好的 hook 链表挂到 fiber 节点的 memorizedState 属性上。

那更新的时候自然也就能从 fiber 节点上取出这个 hook 链表:

react怎么实现hooks

这样在多次渲染中,useXxx 的 api 都能在 fiber 节点上找到对应的 memorizedState。

这就是 react hooks 的原理,可以看到它是把 hook 存在 fiber 节点上的。

那 preact 有什么不同呢?

preact 如何实现 hooks

preact 是兼容 react 代码的更轻量级的框架,它支持 class 组件和 function 组件,也支持了 hooks 等 react 特性。不过它没有实现 fiber 架构。

因为它主要考虑的是体积的极致(只有 3kb),而不是性能的极致。

react怎么实现hooks

刚才我们了解了 react 是把 hook 链表存放在 fiber 节点上的,那 preact 没有 fiber 节点,会把 hook 链表存在哪呢?

其实也很容易想到,fiber 只是对 vdom 做了下改造用于提升性能的,和 vdom 没啥本质的区别,那就把 hook 存在 vdom 上不就行了?

确实,preact 就是把 hook 链表放在了 vdom 上。

比如这个有 4 个 hooks 的函数组件:

react怎么实现hooks

它的实现就是在 vdom 上存取对应的 hook:

react怎么实现hooks

react怎么实现hooks

它没有像 react 那样把 hook 分为 mount 和 update 两个阶段,而是合并到一起处理了。

如图,它把 hooks 存在了 component.__hooks 的数组上,通过下标访问。

这个 component 就是 vdom 上的一个属性:

react怎么实现hooks

也就是把 hooks 的值存在了 vnode._component._hooks 的数组上。

对比下 react 和 preact 实现 hooks 的差异:

所以说,hooks 的实现并不依赖 fiber,它只不过是找个地方存放组件对应的 hook 的数据,渲染时能取到就行,存放在哪里是无所谓的。

因为 vdom、fiber 和组件渲染强相关,所以存放在了这些结构上。

像 react ssr 实现 hooks,就既没有存在 fiber 上,也没有存在 vdom 上:

react ssr 如何实现 hooks

其实 react-dom 包除了可以做 csr 外,也可以做 ssr:

csr 时使用 react-dom 的 render 方法:

react怎么实现hooks

ssr 的时候使用 react-dom/server 的 renderToString 方法或 renderToStream 方法:

react怎么实现hooks

大家觉得 ssr 的时候会做 vdom 到 fiber 的转换么?

肯定不会呀,fiber 是为了提高在浏览器中运行时的渲染性能,把计算变成可打断的,在空闲时做计算,才引入的一种结构。

服务端渲染自然就不需要 fiber。

不需要 fiber 的话,它把 hook 链表存放在哪里呢?vdom 么?

确实可以放在 vdom,但是其实并没有。

比如 useRef 这个 hooks:

react怎么实现hooks

它是从 firstWorkInProgressHook 开始的用 next 串联的一个链表。

react怎么实现hooks

而 firstWorkInProgressHook 最开始用 createHook 创建的第一个 hook 节点:

react怎么实现hooks

并没有挂载到 vdom 上。

为什么呢?

因为 ssr 只需要渲染一次呀,又不需要更新,自然没必要挂到 vdom 上。

只要每次处理完每个组件的 hooks 就清空一下这个 hook 链表就行:

react怎么实现hooks

react怎么实现hooks

react怎么实现hooks

所以,react ssr 时,hooks 是存在全局变量上的。

对比下 react csr 和 ssr 时的 hooks 实现原理的区别:

hooks 的实现原理其实不复杂,就是在某个上下文中存放一个链表,然后 hooks api 从链表不同的元素上访问对应的数据来完成各自的逻辑。这个上下文可以是 vdom、fiber 甚至是全局变量。

不过 hooks 这个思想还是挺火的,淘宝出的服务端框架 midway 就在引入了 hooks 的思想:

midway 如何实现 hooks

midway 是一个 Node.js 框架:

react怎么实现hooks

服务端框架自然就没有 vdom、fiber 这种结构,不过 hooks 的思想并不依赖这些,实现 hooks 的 api 只需要在某个上下文放一个链表就行。

midway 就实现了类似 react hooks 的 api:

react怎么实现hooks

react怎么实现hooks

具体它这个 hook 链表存在哪我还没看,不过我们已经掌握 hooks 的实现原理了,只要有个上下文存放 hook 链表就行,在哪都可以。

到此,关于“react怎么实现hooks”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

阅读原文内容投诉

免责声明:

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

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

软考中级精品资料免费领

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

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

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

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

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

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

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