什么是Fiber

Fiber是React16之后设计的,一种表示vDom节点运行时的对象。

通过模拟链表的数据结构,在Fiber对象中设计了child/sibling/return指针域属性,并存储vDom在调和过程中的工作状态作为数据域,从而形成vDom节点之间依赖关系的链表。

他采用双缓存的机制,基于优先级策略帧间回调的循环任务调度算法,对React的更新渲染过程进行了优化。

Fiber的作用

Fiber架构的设计,将长任务拆分成更小的执行单元,通过时间分片的调度形式取代了之前的递归调和,有效减少了页面阻塞,同时采用的双缓存和优先级策略,提升了vDom遍历的效率,以及重要任务的插队执行,让浏览器交互的响应更为及时,较大优化了性能。

Fiber的数据结构

// react-reconciler\src\ReactFiber.js
/** @note Fiber节点创建 */
function FiberNode(
  this: $FlowFixMe,
  tag: WorkTag,
  pendingProps: mixed,
  key: null | string,
  mode: TypeOfMode,
) {
  // Instance对应的节点实例信息
  this.tag = tag; // Fiber的类型标记
  this.key = key; // Fiber唯一标识符
  this.elementType = null; // ???
  this.type = null; // 组件对应的函数或类,或Dom节点的类型
  this.stateNode = null; // Fiber对应的实例,如类组件的实例,Dom节点的实例
  // Fiber节点关系信息
  this.return = null; // 父Fiber
  this.child = null; // 第一个子Fiber
  this.sibling = null; // 下一个兄弟Fiber
  this.index = 0; // Fiber在父Fiber中的索引
  // ref
  this.ref = null;
  this.refCleanup = null; // 用于清理ref
  // 更新状态相关
  this.pendingProps = pendingProps; // 当前Fiber的props
  this.memoizedProps = null; // 上一次渲染的props
  this.updateQueue = null; // 更新队列
  this.memoizedState = null; // 上一次渲染的state,函数组件则是Hooks信息,DOM则是null
  this.dependencies = null; // context或时间依赖项
  // 模式设置
  this.mode = mode; // Fiber的模式,比如ConcurrentMode、StrictMode等
  // Effects
  this.flags = NoFlags; // Fiber的更新标记,如Placement、Update、Deletion等
  this.subtreeFlags = NoFlags; // 子树的更新标记
  this.deletions = null; // 待删除的子Fiber
  // lane优先级模型
  this.lanes = NoLanes; // Fiber的优先级,17之前是expirationTime
  this.childLanes = NoLanes; // 子树的优先级
  // 双缓存的关键,current Fiber和workInProgress Fiber的关联
  this.alternate = null; // 用于双缓存机制,指向上一次渲染的Fiber
}

Fiber Tag

export const FunctionComponent = 0;       // 函数组件
export const ClassComponent = 1;          // 类组件
export const IndeterminateComponent = 2;  // 初始化的时候不知道是函数组件还是类组件 
export const HostRoot = 3;                // Root Fiber 可以理解为根元素 , 通过reactDom.render()产生的根元素
export const HostPortal = 4;              // 对应  ReactDOM.createPortal 产生的 Portal 
export const HostComponent = 5;           // dom 元素 比如 <div>
export const HostText = 6;                // 文本节点
export const Fragment = 7;                // 对应 <React.Fragment> 
export const Mode = 8;                    // 对应 <React.StrictMode>   
export const ContextConsumer = 9;         // 对应 <Context.Consumer>
export const ContextProvider = 10;        // 对应 <Context.Provider>
export const ForwardRef = 11;             // 对应 React.ForwardRef
export const Profiler = 12;               // 对应 <Profiler/ >
export const SuspenseComponent = 13;      // 对应 <Suspense>
export const MemoComponent = 14;          // 对应 React.memo 返回的组件

Fiber的核心原理

调和Diff方案-双缓存机制

双缓存机制

Fiber.alternate 指向另一个Fiber链表中对应的Fiber节点(双缓存的关键)

WorkInprogress 当前更新过程中构建在内存中的vDom对应的Fiber。更新完成后会将其变为current

Current 当前渲染显示在视图层的vDom对应的Fiber。

优先级策略-lane模型

lane模型

时间分片方案-调度算法

帧间回调的循环事件调度算法:requestIdleCallback(polyfill)