接下来让我们了解下Fiber因何而来?他的作用是什么?

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

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

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

Fiber包含三层含义:

  1. 作为架构来说,之前React15Reconciler采用递归的方式执行,数据保存在递归调用栈中,所以被称为stack ReconcilerReact16Reconciler基于Fiber节点实现,被称为Fiber Reconciler

你可以从这里看到。虽然属性很多,但我们可以按三层含义将他们分类来看

每个Fiber节点有个对应的,多个Fiber节点是如何连接形成树呢?靠如下三个属性:

  1. // 指向父级Fiber节点
  2. this.return = null;
  3. // 指向子Fiber节点
  4. this.child = null;
  5. // 指向右边第一个兄弟Fiber节点
  6. this.sibling = null;

举个例子,如下的组件结构:

对应的Fiber树结构: Fiber架构

这里需要提一下,为什么父级指针叫做return而不是parent或者father呢?因为作为一个工作单元,return指节点执行完completeWork(本章后面会介绍)后会返回的下一个节点。子Fiber节点及其兄弟节点完成工作后会返回其父级节点,所以用return指代父级节点。

作为一种静态的数据结构,保存了组件相关的信息:

  1. // Fiber对应组件的类型 Function/Class/Host...
  2. this.tag = tag;
  3. // key属性
  4. this.elementType = null;
  5. // 对于 FunctionComponent,指函数本身,对于ClassComponent,指class,对于HostComponent,指DOM节点tagName
  6. this.type = null;
  7. // Fiber对应的真实DOM节点
  8. this.stateNode = null;

如下两个字段保存调度优先级相关的信息,会在讲解Scheduler时介绍。

  1. // 调度优先级相关
  2. this.lanes = NoLanes;
  3. this.childLanes = NoLanes;

注意

在2020年5月,调度优先级策略经历了比较大的重构。以expirationTime属性为代表的优先级模型被lane取代。详见

如果你的源码中fiber.expirationTime仍存在,请参照调试源码章节获取最新代码。

本节我们了解了Fiber的起源与架构,其中Fiber节点可以构成Fiber树。那么Fiber树和页面呈现的DOM树有什么关系,React又是如何更新的呢?

我们会在下一节讲解。