React学习笔记 - 基础概念(四) Fiber node 结构

1,194 阅读3分钟

部分比较常见的字段:

  • alternate: current fiber指向work in progress fiber;working in progress fiber指向current fiber
  • stateNode: 保存对组件,DOM节点或与光纤节点关联的其他React元素类型的类实例的引用。通常,我们可以说此属性用于保存与光纤关联的局部状态。
  • type: 定义与此光纤关联的功能或类。对于类组件,它指向构造函数,对于DOM元素,它指定HTML标记。我经常使用此字段来了解光纤节点与哪些元素相关。
  • flags :当前Fiber阶段需要进行任务,包括:占位、更新、删除等 ( Fiber Tree和Effects List
  • tag: 定义[光纤的类型] **。在reconciliation算法中使用它来确定需要完成的工作。如前所述,工作取决于React元素的类型。函数 createFiberFromTypeAndProps 将React元素映射到相应的光纤节点类型
  • updateQueue: 状态更新,回调和DOM更新的队列,Fiber对应的组件,所产生的update,都会放在该队列中
  • memoizedState:当前屏幕UI对应状态,上一次输入更新的Fiber state。
  • pendingProps:新的变动带来的新的props,即nextProps。
  • memoizedProps: 用于在上一次渲染期间创建输出的Fiber的props。
  • dependencies:一个列表,存在该Fiber依赖的contexts,events
  • key(React Element key): 带有一组子代的唯一标识符,以帮助React找出哪些项目已更改,已添加或已从列表中删除。这里讲述了“list和key”之间的关系。
function FiberNode(
  tag: WorkTag,
  pendingProps: mixed,
  key: null | string,
  mode: TypeOfMode,
) {
  // Instance
  // 静态数据存储的属性
  // 定义光纤的类型。在reconciliation算法中使用它来确定需要完成的工作。如前所述,工作取决于React元素的类型。函数createFiberFromTypeAndProps将React元素映射到相应的光纤节点类型
  this.tag = tag;
  this.key = key;
  this.elementType = null;
  // 定义与此光纤关联的功能或类。对于类组件,它指向构造函数,对于DOM元素,它指定HTML标记。我经常使用此字段来了解光纤节点与哪些元素相关。
  this.type = null;
  // 保存对组件,DOM节点或与光纤节点关联的其他React元素类型的类实例的引用。通常,我们可以说此属性用于保存与光纤关联的局部状态。
  this.stateNode = null;

  // Fiber
  // Fiber关系相关属性,用于生成Fiber Tree结构
  this.return = null;
  this.child = null;
  this.sibling = null;
  this.index = 0;

  this.ref = null;

  // 动态数据&状态相关属性
  // new props,新的变动带来的新的props,即nextProps
  this.pendingProps = pendingProps;
  // prev props,用于在上一次渲染期间创建输出的Fiber的props
  this.memoizedProps = null;
  // 状态更新,回调和DOM更新的队列,Fiber对应的组件,所产生的update,都会放在该队列中
  this.updateQueue = null;
  // 当前屏幕UI对应状态,上一次输入更新的Fiber state
  this.memoizedState = null;
  // 一个列表,存储该Fiber依赖的contexts,events
  this.dependencies = null;
  
  // conCurrentMode和strictMode
  // 共存的模式表示这个子树是否默认是 异步渲染的
  // Fiber刚被创建时,会继承父Fiber
  this.mode = mode;

  // Effects
  // 当前Fiber阶段需要进行任务,包括:占位、更新、删除等
  this.flags = NoFlags;
  this.subtreeFlags = NoFlags;
  this.deletions = null;

  // 优先级调度相关属性
  this.lanes = NoLanes;
  this.childLanes = NoLanes;

  // current tree和working in prgoress tree关联属性
  // 在FIber树更新的过程中,每个Fiber都有与其对应的Fiber
  // 我们称之为 current <==> workInProgress
  // 在渲染完成后,会指向对方
  this.alternate = null;

  // 探查器记录的相关时间
  if (enableProfilerTimer) {
    // Note: The following is done to avoid a v8 performance cliff.
    //
    // Initializing the fields below to smis and later updating them with
    // double values will cause Fibers to end up having separate shapes.
    // This behavior/bug has something to do with Object.preventExtension().
    // Fortunately this only impacts DEV builds.
    // Unfortunately it makes React unusably slow for some applications.
    // To work around this, initialize the fields below with doubles.
    //
    // Learn more about this here:
    // https://github.com/facebook/react/issues/14365
    // https://bugs.chromium.org/p/v8/issues/detail?id=8538
    this.actualDuration = Number.NaN;
    this.actualStartTime = Number.NaN;
    this.selfBaseDuration = Number.NaN;
    this.treeBaseDuration = Number.NaN;

    // It's okay to replace the initial doubles with smis after initialization.
    // This won't trigger the performance cliff mentioned above,
    // and it simplifies other profiler code (including DevTools).
    this.actualDuration = 0;
    this.actualStartTime = -1;
    this.selfBaseDuration = 0;
    this.treeBaseDuration = 0;
  }

  if (__DEV__) {
    // This isn't directly used but is handy for debugging internals:

    this._debugSource = null;
    this._debugOwner = null;
    this._debugNeedsRemount = false;
    this._debugHookTypes = null;
    if (!hasBadMapPolyfill && typeof Object.preventExtensions === 'function') {
      Object.preventExtensions(this);
    }
  }
}