什么是Fiber
当面试官问我们什么是Fiber时我们可以从下面几个方面更全面的回答这个问题。
- 是一种架构,称之为 Fiber 架构
- 是一种描述Dom的数据结构(链表)
- 动态的工作单元,每个Fiber Node都记录自己的完整信息
可以从浏览器复制一个元素查看他的Fiber对象
如上图是一个img的FiberNode,上面记录的信息有:
- child 子节点
- elementType元素类型
- memoizedProps 记录传入的props
- memoizedState 记录组件状态
- ref dom的引用就是useRef
- return 自己父级的Fiber Node
- alternate 指向自己更新前/后的FiberNode
- 以及其他和调度有关的属性
Fiber 双缓冲
显卡分为前缓冲区和后缓冲区。首先,前缓冲区会显示图像,之后,合成的新的图像会被写入到后缓冲区,一旦后缓冲区写入图像完毕,就会前后缓冲区进行一个互换,这种将数据保存在缓冲区再进行互换的技术,就被称之为双缓冲技术。
Fiber 架构同样用到了这个技术,在 Fiber 架构中,同时存在两颗 Fiber Tree,一颗是真实 UI 对应的 Fiber Tree,可以类比为显卡的前缓冲区,另外一颗是在内存中构建的 FiberTree,可以类比为显卡的后缓冲区。
current 指的就是前缓冲区的 FiberNode,workInProgress 指的就是后缓冲区的 FiberNode。
两个 FiberNode 会通过 alternate 属性相互指向。
接下来我们从首次渲染(mount)和更新(update)这两个阶段来看一下 FiberTree 的形成以及双缓存机制:
mount 阶段
首先最顶层有一个 FiberNode,称之为 FiberRootNode,该 FiberNode 会有一些自己的任务:
- Current Fiber Tree 与 Wip Fiber Tree 之间的切换
- 应用中的过期时间
- 应用的任务调度信息
此时会有一个 HostRootFiber,FiberRootNode 通过 current 来指向 HostRootFiber。
在mount阶段 current fiber tree 只有一个HostRootFiber节点,需要创建一个新的workInProgress。
生成的 wip FiberTree 里面的每一个 FiberNode 会和 current FiberTree 里面的 FiberNode进行关联,关联的方式就是通过 alternate。但是目前 currentFiberTree里面只有一个 HostRootFiber,因此就只有这个 HostRootFiber 进行了 alternate 的关联。
当 wip FiberTree生成完毕后,也就意味着 render 阶段完毕了,此时 FiberRootNode就会被传递给 Renderer(渲染器),接下来就是进行渲染工作。渲染工作完毕后,浏览器中就显示了对应的 UI,此时 FiberRootNode.current 就会指向这颗 wip Fiber Tree,曾经的 wip Fiber Tree 它就会变成 current FiberTree,完成了双缓存的工作。如下图
update阶段
在首次mount阶段结束后,后续的更新流程为:
-
复制 current Fiber 树为 work-in-progress Fiber 树:在每次更新过程开始时,React Fiber 会将 current Fiber 树复制一份,作为 work-in-progress Fiber 树。work-in-progress Fiber 树是用来进行差异计算和更新的。
-
根据 React 组件对 work-in-progress Fiber 树进行调整:在对 work-in-progress Fiber 树进行差异计算和更新之前,React Fiber 会根据 React 组件对 work-in-progress Fiber 树进行调整,以更新组件树的状态和属性。这个过程通常被称为“协调(reconciliation)”。
-
Diff 对比 current Fiber 树和 work-in-progress Fiber 树:在对 work-in-progress Fiber 树进行调整之后,React Fiber 会将 work-in-progress Fiber 树和 current Fiber 树进行对比,找出它们之间的差异,并记录下来。这个过程通常被称为“diff(差异计算)”。
所谓 Fiber 双缓冲树,指的是在内存中构建两颗树,并直接在内存中进行替换的技术。在 React 中使用 Wip Fiber Tree 和 Current Fiber Tree 这两棵树来实现更新的逻辑。Wip Fiber Tree 在内存中完成更新,而 Current Fiber Tree 是最终要渲染的树,两棵树通过 alternate 指针相互指向,这样在下一次渲染的时候,直接复用 Wip Fiber Tree 作为下一次的渲染树,而上一次的渲染树又作为新的 Wip Fiber Tree,这样可以加快 DOM 节点的替换与更新。