目录
react 如何实现 hooks
preact 如何实现 hooks
react ssr 如何实现 hooks
midway 如何实现 hooks
总结
首页 web前端 js教程 react如何实现hooks?必须依赖 Fiber 么?

react如何实现hooks?必须依赖 Fiber 么?

Apr 20, 2022 pm 08:52 PM
react

react如何实现hooks?React Hooks 的实现必须依赖 Fiber 么?下面本篇文章带大家来看看不同框架中的 hooks 都是怎么实现的,希望对大家有所帮助!

react如何实现hooks?必须依赖 Fiber 么?

React 的 hooks 是在 fiber 之后出现的特性,所以很多人误以为 hooks 是必须依赖 fiber 才能实现的,其实并不是,它们俩没啥必然联系。【相关推荐:Redis视频教程

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

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

react 如何实现 hooks

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

1.png

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

2.png

在 React 17 之后换成了 jsx:

3.png

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

render function 执行产生 vdom:

4.png

vdom 的结构是这样的:

5.png

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

6.png

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

7.png

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

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

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

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

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

fiber 节点的结构是这样的:

8.png

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

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

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

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

9.png

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

10.png

通过 next 串联起来:

11.png

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

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

12.png

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

13.png

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

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

14.png

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

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

那 preact 有什么不同呢?

preact 如何实现 hooks

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

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

15.png

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

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

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

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

16.png

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

17.png

18.png

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

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

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

19.png

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

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

  • react 中是把 hook 链表存放在 fiberNode.memorizedState 属性上,preact 中是把 hook 链表存放在 vnode._component._hooks 属性上

  • react 中的 hook 链表通过 next 串联,preact 中的 hook 链表就是个数组,通过下标访问

  • react 把 hook 链表的创建和更新分离开,也就是 useXxx 会分为 mountXxx 和 updateXxx 来实现,而 preact 中合并在一起处理的

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

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

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

react ssr 如何实现 hooks

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

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

20.png

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

21.png

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

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

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

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

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

比如 useRef 这个 hooks:

22.png

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

23.png

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

24.png

并没有挂载到 vdom 上。

为什么呢?

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

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

25.png

26.png

27.png

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

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

  • csr 时会从 vdom 创建 fiber,用于把渲染变成可打断的,通过空闲调度来提高性能,而 ssr 时不会,是 vdom 直接渲染的

  • csr 时把 hooks 保存到了 fiber 节点上,ssr 时是直接放在了全局变量上,每个组件处理完就清空。因为不会用第二次了

  • csr 时会把 hook 的创建和更新分为 mount 和 update 两个阶段,而 ssr 因为只会处理一次,只有创建阶段

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

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

midway 如何实现 hooks

midway 是一个 Node.js 框架:

28.png

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

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

29.png

30.png

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

总结

react hooks 是在 react fiber 架构之后出现的特性,很多人误以为 hooks 必须配合 fiber 才能实现,我们分别看了 react、preact、react ssr、midway 中的 hooks 的实现,发现并不是这样的:

  • react 是把 vdom 转成 fiber,然后把 hook 链表存放到了 fiber.memorizedState 属性上,通过 next 串联
  • preact 没有实现 fiber,它是把 hook 链表放到了 vnode._component._hooks 属性上,数组实现的,通过下标访问
  • react ssr 时不需要 fiber,但是也没有把 hook 链表挂到 vdom 上,而是直接放在了一个全局变量上,因为只需要渲染一次,渲染完一个组件就清空这个全局变量就行
  • midway 是一个 Node.js 框架,它也实现了 hooks 类似的 api,具体放在哪我们没深入,但是只要有个上下文存放 hook 链表就行

所以,react hooks 必须依赖 fiber 才能实现么?

明显不是,搭配 fiber、搭配 vdom、搭配全局变量,甚至任何一个上下文都可以。

更多编程相关知识,请访问:编程视频!!

以上是react如何实现hooks?必须依赖 Fiber 么?的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

<🎜>:泡泡胶模拟器无穷大 - 如何获取和使用皇家钥匙
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系统,解释
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆树的耳语 - 如何解锁抓钩
3 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

热门话题

Java教程
1666
14
CakePHP 教程
1425
52
Laravel 教程
1324
25
PHP教程
1272
29
C# 教程
1251
24
如何利用React和RabbitMQ构建可靠的消息传递应用 如何利用React和RabbitMQ构建可靠的消息传递应用 Sep 28, 2023 pm 08:24 PM

如何利用React和RabbitMQ构建可靠的消息传递应用引言:现代化的应用程序需要支持可靠的消息传递,以实现实时更新和数据同步等功能。React是一种流行的JavaScript库,用于构建用户界面,而RabbitMQ是一种可靠的消息传递中间件。本文将介绍如何结合React和RabbitMQ构建可靠的消息传递应用,并提供具体的代码示例。RabbitMQ概述:

React Router使用指南:如何实现前端路由控制 React Router使用指南:如何实现前端路由控制 Sep 29, 2023 pm 05:45 PM

ReactRouter使用指南:如何实现前端路由控制随着单页应用的流行,前端路由成为了一个不可忽视的重要部分。ReactRouter作为React生态系统中最受欢迎的路由库,提供了丰富的功能和易用的API,使得前端路由的实现变得非常简单和灵活。本文将介绍ReactRouter的使用方法,并提供一些具体的代码示例。安装ReactRouter首先,我们需

PHP、Vue和React:如何选择最适合的前端框架? PHP、Vue和React:如何选择最适合的前端框架? Mar 15, 2024 pm 05:48 PM

PHP、Vue和React:如何选择最适合的前端框架?随着互联网技术的不断发展,前端框架在Web开发中起着至关重要的作用。PHP、Vue和React作为三种具有代表性的前端框架,每一种都具有其独特的特点和优势。在选择使用哪种前端框架时,开发人员需要根据项目需求、团队技能和个人偏好做出明智的决策。本文将通过比较PHP、Vue和React这三种前端框架的特点和使

Java框架与前端React框架的整合 Java框架与前端React框架的整合 Jun 01, 2024 pm 03:16 PM

Java框架与React框架的整合:步骤:设置后端Java框架。创建项目结构。配置构建工具。创建React应用。编写RESTAPI端点。配置通信机制。实战案例(SpringBoot+React):Java代码:定义RESTfulAPI控制器。React代码:获取并显示API返回的数据。

如何利用React开发一个响应式的后台管理系统 如何利用React开发一个响应式的后台管理系统 Sep 28, 2023 pm 04:55 PM

如何利用React开发一个响应式的后台管理系统随着互联网的快速发展,越来越多的企业和组织需要一个高效、灵活、易于管理的后台管理系统来处理日常的操作事务。React作为目前最受欢迎的JavaScript库之一,提供了一种简洁、高效和可维护的方式来构建用户界面。本文将介绍如何利用React开发一个响应式的后台管理系统,并给出具体的代码示例。创建React项目首先

vue.js vs.反应:特定于项目的考虑因素 vue.js vs.反应:特定于项目的考虑因素 Apr 09, 2025 am 12:01 AM

Vue.js适合中小型项目和快速迭代,React适用于大型复杂应用。1)Vue.js易于上手,适用于团队经验不足或项目规模较小的情况。2)React的生态系统更丰富,适合有高性能需求和复杂功能需求的项目。

React在HTML中的作用:增强用户体验 React在HTML中的作用:增强用户体验 Apr 09, 2025 am 12:11 AM

React通过JSX与HTML结合,提升用户体验。1)JSX嵌入HTML,使开发更直观。2)虚拟DOM机制优化性能,减少DOM操作。3)组件化管理UI,提高可维护性。4)状态管理和事件处理增强交互性。

react有哪些闭包 react有哪些闭包 Oct 27, 2023 pm 03:11 PM

react有事件处理函数、useEffect和useCallback、高阶组件等等闭包。详细介绍:1、事件处理函数闭包:在React中,当我们在组件中定义一个事件处理函数时,该函数会形成一个闭包,可以访问组件作用域内的状态和属性。这样可以在事件处理函数中使用组件的状态和属性,实现交互逻辑;2、useEffect和useCallback中的闭包等等。

See all articles