React 每一次大的版本更新都来带来一些新的概念或者专有名词,在 React16 之后带来了很多新的特性,例如 hooks,ErrorBoundary,新的 Context 实现方案,fiber 等等。本文主要针对 react fiber 做一个简单的介绍
为什么需要 react fiber
react fiber 是 react 对 react 15 重构过程中产出的一种新的概念,那么现在思考一下为什么要重构?是旧版本有什么缺点呢?还是为了完成新的 KPI???🤡
React 重构的背景
我们都知道 React 离不开虚拟 DOM,在状态变更时需要构建新的虚拟 DOM 树并进行新旧 DOM DIFF 计算,这一个过程叫做 reconcilation(协调)过程,然而 React 旧的版本依赖于栈结构,所以整个过程叫做 stack reconciliation(栈协调)。栈的一个明显的缺点就是无法中断,暂停和恢复。每次状态变更开始同步递归遍历组件树构建虚拟 DOM 树=>根据 DIFF 算法找出差异=>Patch 差异,整个过程无法中断,一旦组件树过于庞大,整个过程如果耗时大于 16ms,那么就会阻塞浏览器渲染和用户交互等操作,导致卡顿现象,影响用户体验。
双向链表
既然栈这种数据结构无法中断,暂停和恢复,React 想出了一种新的数据结构来代替栈,那就是双向链表。现在 React 描述组件树的结构如下
一个 Fiber Node 的定义如下
https://github.com/facebook/react/blob/3dc41d8a2590768a6ac906cd1f4c11ca00417eee/packages/react-reconciler/src/ReactFiber.new.js#L114-L191
FiberNode 的部分属性含义,return
代表父节点,child
代表子节点 ,sibling
代表兄弟节点,还有一些存储新旧 props 的 memorizedProps
和 pendingProps
,状态存储的 memoizedState
等
比如现在有这样一个组件
const App = () => {
return (
<div className="container">
<a href="1024nav.com">1024nav</a>
<h1>前端面经</h1>
</div>
);
};
生成的 Fiber Tree 结点如下

fiber 如何工作
创建 fiber node 结点
创建 fiber node 通过 createFiberFromTypeAndProps
方法判断 fiberTag 的类型,fiberTag 的定义可以点击查看
https://github.com/facebook/react/blob/3dc41d8a2590768a6ac906cd1f4c11ca00417eee/packages/react-reconciler/src/ReactFiber.new.js#L464-L471
然后通过 createFiber
方法来创建节点
https://github.com/facebook/react/blob/3dc41d8a2590768a6ac906cd1f4c11ca00417eee/packages/react-reconciler/src/ReactFiber.new.js#L577-L580
requestIdleCallback 实现任务调度
requestIdleCallback
可以在浏览器空闲的时候被调用,可以让开发人员在主事件循环执行低优先级任务,从而不影响浏览器的动画和用户输入等高优先级的任务。发生的时机是下一次通过事件循环之前
react 通过自己实现的 requestIdleCallback
来实现任务的调度,具体代码可以下面查阅
https://github.com/facebook/react/blob/eeb817785c771362416fd87ea7d2a1a32dde9842/packages/scheduler/src/Scheduler.js#L212-L222
总结
react 使用了新的 fiber 架构,但是底层的核心 diff 算法还是保持与旧的一致,比如不同的组件类型同样是销毁重新创建,对于列表渲染仍然需要 key 来标记优化等
fiber 的对任务排了优先级,对 UI 交互和动画渲染等任务优先执行,对 DOM diff 计算等任务延后执行
每个 fiber 代表每一个工作单元,react 通过重新实现了一个虚拟栈桢,可以方便任务调度,每一个工作单元可以中断,暂停和重启,这也是 react 新版本对生命周期做了调整的原因
通过自定义
requestIdleCallback
方法,可以在浏览器空闲的时候执行低优先级的任务