• Fiber的理解


    Fiber的理解

    代数效应

    React 团队核心成员 – React hooks 的发明者 Sebastian Markbage 曾说:在 react 中做的就是践行代数效应

    代数效应:是函数式编程中的概念,用于将副作用从函数调用中分离,使函数的关注点保持纯粹


    React 如何应用代数效应: 代数效应和 react 中的联系就是 hooks

    举个🌰:使用 useState 返回了一个 num 和 updatenum 的方法,num的值会显示在 button 中,点击btn后num值会加1,我们只需要考虑num如何展示以及更新逻辑是怎么样的,至于num是如何保存在函数式组件的这些完全交给 react去处理,实现了将副作用从函数调用中分离。


    fiber 架构与代数效应的关系

    fiber架构就是利用了代数效应中 异步可中断更新的原理(async 的执行原理就是类似于 异步可中断更新机制,但是有一定区别)


    fiber 架构

    在这里插入图片描述

    fiber 翻译过来是纤程,与进程,线程,协程同为操作系统程序的执行过程,可以将纤程理解为协程的一种实现,(协程在js中有一个应用,就是 generator 的实现)


    为什么不选择协程实现异步可中断

    那为什么不使用 协程来实现异步可中断的更新,而要自己实现一套纤程呢?

    16年在 github 上有一篇 fiber 的 issue 文章中找到了答案:
    在这里插入图片描述

    1. generator 也和 async await 一样,也是有传染性的,当某个函数变成 generator 后,调用链的其他函数也会收到影响
    2. 第二个,也是最重要的原因,设计 fiber 架构的初衷是为了达到两个目的
      1. 更新可以被中断,也可以继续
      2. 更新可以拥有不同的优先级,高优先级的可以打断低优先级的更新

    使用 generator 可以达到 2.1 的目的,但是不能达到2.2的目的


    fiber 的含义

    作为架构来说

    react 15 的协调器(reconciler)采用递归的方式执行,数据保存在递归的调用栈中,所以其实也被称为 stack reconciler。
    react 16 的调节器是基于 fiber 节点实现的,所以被称为 fiber reconciler。


    作为静态的数据结构来说

    每个 fiber 节点对应一个组件,保存了该组件的类型和对应的dom节点信息,这时的fiber节点也就是我们所说的虚拟 dom,

    举个例子:比如说有个 app组件,当我们首次调用 reactdom.render 时,会创建整个应用的根结点FiberRootNode ,由于我们可以多次调用 render 方法,将不同的应用挂载到不同的 dom 节点下,所以每个应用都有自己的 RootFiber 节点,在一个页面中有多个 rootfiber 节点,但是只能有一个FiberRootNode 来管理这些 RootFiber

    在这里插入图片描述

    可能会问,为啥子节点是child,父节点确是用 return 来连接呢?

    因为 react15 中的 stack reconciler 采用递归的方式工作,当从根结点开始执行递归操作时,首先会从根结点一直递归到子节点,再从子节点一路向上回到根结点,所以函数在处理完了了子节点之后,会返回他的父节点;在 fiber reconciler 中,采用遍历的欣赏,实现可中断的递归,所以也复用了这种思想,所以就用return 代表了父节点。

    在这里插入图片描述

    如果只是作为静态的数据结构,fiber 和 jsx 没有什么区别


    作为动态的工作单元

    fiber 节点保存了组件需要更新的状态以及需要执行的副作用,依次是作为静态数据结构,作为架构来说(return,child,sibling 指针会将fiber节点连接成一个树),作为动态的工作单元(其中带有 effect 的是代表副作用相关的,对于 host component ,副作用有增删改查,对于 function component,副作用代表的是 useEffect 和 uselayoutEffect 这两个hook,和 lane 相关的属性和 优先级调度有关,最后一个 alternate 属性关系到了 fiber 架构的工作方式

    在这里插入图片描述


    fiber 的工作机制:双缓存

    fiber 架构使用一种叫双缓存的工作机制


    双缓存:
    首先了解动画的原理:动画由多张连续的图片组成,每一张图称为动画的一帧,当我们播放动画时,以一定的速度连续展示每一帧的图片,在动画的展示区域,在渲染新的一帧时会将前一帧的图片清除,如果从清除前一帧图片到展示下一帧的图片消耗的时间过长,就会出现人眼能感知的白屏闪烁,为解决这个问题,出现了 双缓存。

    在内存中绘制当前帧的图片,绘制完成后,直接用当前帧替换上一帧的图片,由于省出来两帧替换帧所消耗的时间,不会出现白屏或者画面闪烁的情况,这种在内存中构建并直接替换的技术就叫双缓存


    双缓存工作原理
    1. 当首次调用 ReactDOM.render 时,会创建整个应用的根结点 FiberRootNode;每次调用 ReactDOM.render,都会创建当前应用的根结点 RoottFiber,通过 current 指针连接,由于在首屏渲染之前,页面是空白的,所以 RootFiber 没有子节点

    1. 无论是首屏渲染还是更新,都会从根节点开始创建一个 fiber 树,首先创建 fiber树的根节点 RootFiber,这两棵fiber树中都存在 fiber节点,会用 alternate 指针连接,方便两棵fiber树之间共用一些属性,接下来采用深度优先遍历,模拟递归的方式创建整棵 fiber 树。现在拥有两棵fiber树,左侧代表页面内容的fiber树 current Fiber 树,右侧由于触发了更新,在内存中构建的 fiber树称为 workInProgress Fiber 树

    在这里插入图片描述

    1. 当 workInProgress fiber 树完成了渲染,此时 FiberRootNode 的 current 指针就指向了workInProgress fiber 树的根节点,于是 workInProgress fiber 树 就变成了 current fiber 树

    每次触发更新,都会重新创建一个 workInProgress fiber 树,将 current fiber 树 的节点称为 current 节点,此时 current RootFiber 的 alternate 指针已经指向了一个 RootFiber,所以在创建新的 workInProgress fiber 树时,会基于这个 RootFiber 创建。

    这种将 current fiber 与本次更新返回的 JSX 结构进行对比生成 workInProgress fiber 树的过程就是 diff 算法,所以首屏渲染与更新的区别就是在创建 fiber 树的过程中 是否有 diff 算法


    1. 当 workInProgress fiber 树最终完成了渲染,current 指针指向了 workInProgress 的根节点,至此,当前的 workInProgress fiber 树 变为了 current fiber 树

    总结

    在这里插入图片描述


    参考文献:
    https://github.com/acdlite/react-fiber-architecture
    https://www.bilibili.com/video/BV1vP4y1w7TN
    https://ke.segmentfault.com/course/1650000023864436/section/1500000023865956

  • 相关阅读:
    [大模型]Llama-3-8B-Instruct FastApi 部署调用
    TSINGSEE青犀智慧工厂视频汇聚与安全风险智能识别和预警方案
    【yarn】CDP集群 Yarn配置capacity调度器批量分配
    云安虚拟化应用性能监测系统—应用异常检测
    16. 机器学习——决策树
    codeforces:F. All Possible Digits【贪心 + 模拟进位】
    互联网技术从业者怎么解决系统高并发?
    积分商城可设置的四种兑换商品类型
    花2w培训数据分析真的值得吗?
    协议栈——连接服务器
  • 原文地址:https://blog.csdn.net/qq_45803050/article/details/127445926