Skip to content

React Note - Fiber #17

@wwyx778

Description

@wwyx778

React Fiber

最早的Fiber官方解释来源于2016年React团队成员Acdlite的一篇介绍 (opens new window)。

从上一章的学习我们知道:

在React15及以前,Reconciler采用递归的方式创建虚拟DOM,递归过程是不能中断的。如果组件树的层级很深,递归会占用线程很多时间,造成卡顿。

为了解决这个问题,React16将递归的无法中断的更新重构为异步的可中断更新,由于曾经用于递归的虚拟DOM数据结构已经无法满足需要。于是,全新的Fiber架构应运而生。


双缓存Fiber树

双缓存也被称为离屏渲染,在 React 中最多会同时存在两棵Fiber树。当前屏幕上显示内容对应的Fiber树称为 current Fiber 树,正在内存中构建的Fiber树称为 workInProgress Fiber 树。

current Fiber 树中的 Fiber 节点被称为 currentFiber,workInProgress Fiber树中的Fiber节点被称为 workInProgressFiber,他们通过alternate属性连接。

currentFiber.alternate === workInProgressFiber;
workInProgressFiber.alternate === currentFiber;

React 应用的根节点通过使 current 指针在不同 Fiber 树的 rootFiber 间切换来完成 current Fiber 树指向的切换。

即当 workInProgress Fiber 树构建完成交给 Renderer 渲染在页面上后,应用根节点的 current 指针指向 workInProgress Fiber 树,此时 workInProgress Fiber 树就变为 current Fiber 树。

每次状态更新都是一次 workInProgress Fiber 树和 current Fiber 树的职能交换的过程,完成DOM更新。

时间切片原理

React 时间切片的本质是 React 对 requestIdleCallback 的模拟实现

除去“浏览器重排/重绘”,下面是浏览器一帧中可以用于执行JS的时机。

  • task(宏任务)
  • 队列中全部job(微任务)
  • requestAnimationFrame
  • 浏览器重排/重绘
  • requestIdleCallback

React 的时间切片(Scheduler)是通过 setTimeoutMessageChannel实现的。
React 会优先使用 MessageChannel,如果宿主环境不支持 MessageChannel,则使用 setTimeout

在 React 的 render 阶段,开启 Concurrent Mode 时,每次遍历前,都会通过 Scheduler 提供的 shouldYield 方法判断是否需要中断遍历,使浏览器有时间渲染,是否中断的依据,最重要的一点便是每个任务的剩余时间是否用完。在Scheduler中,为任务分配的初始剩余时间为5ms。

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions