资讯专栏INFORMATION COLUMN

React源码解析之RootFiber

libin19890520 / 1750人阅读

摘要:一的含义和作用每一个对应一个对象记录节点的各种状态比如中的和的状态就是记录在对象上的。只有当对象更新后,才会更新到上的和上上的和是根据对象的更新的。

一、Fiber的含义和作用
(1)每一个ReactElement对应一个Fiber对象

(2)记录节点的各种状态
比如ClassComponent中的stateprops的状态就是记录在Fiber对象上的。

只有当Fiber对象更新后,才会更新到ClassComponent上的this.statethis.props

this上的stateprops是根据Fiber对象的stateprops更新的。

这实际上也方便了ReactHooks,因为hooks是为FunctionalComponent服务的。虽然FunctionalComponent没有this,但Fiber上有,是可以拿到stateprops

(3)串联整个应用形成树结构
每个ReactElement通过props.children与其他ReactElement连结起来

说明:
ReactElement只会把子节点(props.children)的第一个子节点当做child节点,其余的子节点(也就是第一个子节点的兄弟节点)都是从第一个子节点开始,依次单向连接至后一个兄弟节点

② 每个子节点都会指向父节点(红箭头),也就是Fiber对象的return属性

export type Fiber = {|
  //指向该对象在Fiber节点树中的`parent`,用来在处理完该节点后返回
  //即流程图上的红线
  return: Fiber | null,
}

串联过程:
① 任一 叶子 节点A,如果有兄弟节点,则去单向向后遍历兄弟节点,最后return到父节点
② 父节点的child节点不是刚刚的子节点A的话,则从child节点遍历到A前的节点,并再次return到父节点
③ 该父节点执行 ①、②

根据图1举例:
比如从左下角的input节点开始,它没有兄弟节点,则return到父组件Input(因为父节点有且只有一个,所以必定return到父节点)

Input有兄弟节点ListList又有child节点,则从child节点往后单向遍历兄弟节点,最后returnList

Listreturndivdivchild节点已被遍历,则returnApp节点,AppAppreturn到所有Fiber对象的根对象RootFiber对象

这样,就将整个应用遍历完了。

二、Fiber对象
源码:

// A Fiber is work on a Component that needs to be done or was done. There can
// be more than one per component.

//Fiber对应一个即将update或已经update的组件,
// 一个组件可以有一个或多个Fiber
export type Fiber = {|
  // These first fields are conceptually members of an Instance. This used to
  // be split into a separate type and intersected with the other Fiber fields,
  // but until Flow fixes its intersection bugs, we"ve merged them into a
  // single type.

  // An Instance is shared between all versions of a component. We can easily
  // break this out into a separate object to avoid copying so much to the
  // alternate versions of the tree. We put this on a single object for now to
  // minimize the number of objects created during the initial render.

  // Tag identifying the type of fiber.

  //标记不同的组件类型
  //有原生的DOM节点,有React自己的节点
  tag: WorkTag,

  // Unique identifier of this child.

  //ReactElement里面的key
  key: null | string,

  // The value of element.type which is used to preserve the identity during
  // reconciliation of this child.

  //ReactElement.type,也就是我们调用createElement的第一个参数
  elementType: any,

  // The resolved function/class/ associated with this fiber.

  //异步组件resolve之后返回的内容,一般是function或class
  //比如懒加载
  type: any,

  // The local state associated with this fiber.

  //当前Fiber的状态(比如浏览器环境就是DOM节点)

  //不同类型的实例都会记录在stateNode上
  //比如DOM组件对应DOM节点实例
  //ClassComponent对应Class实例
  //FunctionComponent没有实例,所以stateNode值为null

  //state更新了或props更新了均会更新到stateNode上
  stateNode: any,

  // Conceptual aliases
  // parent : Instance -> return The parent happens to be the same as the
  // return fiber since we"ve merged the fiber and instance.

  // Remaining fields belong to Fiber

  // The Fiber to return to after finishing processing this one.
  // This is effectively the parent, but there can be multiple parents (two)
  // so this is only the parent of the thing we"re currently processing.
  // It is conceptually the same as the return address of a stack frame.

  //指向该对象在Fiber节点树中的`parent`,用来在处理完该节点后返回
  //即流程图上的红线
  return: Fiber | null,

  // Singly Linked List Tree Structure.
  //单链表树结构

  //指向自己的第一个子节点
  child: Fiber | null,

  //指向自己的兄弟结构
  //兄弟节点的return指向同一个父节点
  sibling: Fiber | null,
  index: number,

  // The ref last used to attach this node.
  // I"ll avoid adding an owner field for prod and model that as functions.

  //ref属性
  ref: null | (((handle: mixed) => void) & {_stringRef: ?string}) | RefObject,

  // Input is the data coming into process this fiber. Arguments. Props.

  //新的变动带来的新的props,即nextProps
  pendingProps: any, // This type will be more specific once we overload the tag.

  //上一次渲染完成后的props,即 props
  memoizedProps: any, // The props used to create the output.

  // A queue of state updates and callbacks.

  //该Fiber对应的组件,所产生的update,都会放在该队列中
  updateQueue: UpdateQueue | null,

  // The state used to create the output

  //上次渲染的state,即 state
  //新的state由updateQueue计算得出,并覆盖memoizedState
  memoizedState: any,

  // Dependencies (contexts, events) for this fiber, if it has any

  //一个列表,存在该Fiber依赖的contexts,events
  dependencies: Dependencies | null,

  // Bitfield that describes properties about the fiber and its subtree. E.g.
  // the ConcurrentMode flag indicates whether the subtree should be async-by-
  // default. When a fiber is created, it inherits the mode of its
  // parent. Additional flags can be set at creation time, but after that the
  // value should remain unchanged throughout the fiber"s lifetime, particularly
  // before its child fibers are created.

  //mode有conCurrentMode和strictMode

  //用来描述当前Fiber和其他子树的Bitfield
  //共存的模式表示这个子树是否默认是 异步渲染的

  //Fiber刚被创建时,会继承父Fiber
  //其他标识也可以在创建的时候被设置,但是创建之后不该被修改,特别是它的子Fiber创建之前
  mode: TypeOfMode,

  //以下属性是副作用
  //副作用是 标记组件哪些需要更新的工具、标记组件需要执行哪些生命周期的工具

  // Effect
  effectTag: SideEffectTag,

  // Singly linked list fast path to the next fiber with side-effects.
  nextEffect: Fiber | null,

  // The first and last fiber with side-effect within this subtree. This allows
  // us to reuse a slice of the linked list when we reuse the work done within
  // this fiber.
  firstEffect: Fiber | null,
  lastEffect: Fiber | null,

  // Represents a time in the future by which this work should be completed.
  // Does not include work found in its subtree.

  //代表任务在未来的哪个时间点 应该被完成
  //不包括该Fiber的子树产生的任务
  expirationTime: ExpirationTime,

  // This is used to quickly determine if a subtree has no pending changes.

  //快速确定子树中是否有 update
  //如果子节点有update的话,就记录应该更新的时间
  childExpirationTime: ExpirationTime,

  // This is a pooled version of a Fiber. Every fiber that gets updated will
  // eventually have a pair. There are cases when we can clean up pairs to save
  // memory if we need to.

  // 在FIber树更新的过程中,每个Fiber都有与其对应的Fiber
  //我们称之为 current <==> workInProgress
  //在渲染完成后,会交换位置

  //doubleBuffer Fiber在更新后,不用再重新创建对象,
  // 而是复制自身,并且两者相互复用,用来提高性能

  alternate: Fiber | null,

  // Time spent rendering this Fiber and its descendants for the current update.
  // This tells us how well the tree makes use of sCU for memoization.
  // It is reset to 0 each time we render and only updated when we don"t bailout.
  // This field is only set when the enableProfilerTimer flag is enabled.
  actualDuration?: number,

  // If the Fiber is currently active in the "render" phase,
  // This marks the time at which the work began.
  // This field is only set when the enableProfilerTimer flag is enabled.
  actualStartTime?: number,

  // Duration of the most recent render time for this Fiber.
  // This value is not updated when we bailout for memoization purposes.
  // This field is only set when the enableProfilerTimer flag is enabled.
  selfBaseDuration?: number,

  // Sum of base times for all descedents of this Fiber.
  // This value bubbles up during the "complete" phase.
  // This field is only set when the enableProfilerTimer flag is enabled.
  treeBaseDuration?: number,

  // Conceptual aliases
  // workInProgress : Fiber ->  alternate The alternate used for reuse happens
  // to be the same as work in progress.
  // __DEV__ only
  _debugID?: number,
  _debugSource?: Source | null,
  _debugOwner?: Fiber | null,
  _debugIsCurrentlyTiming?: boolean,
  _debugNeedsRemount?: boolean,

  // Used to verify that the order of hooks does not change between renders.
  _debugHookTypes?: Array | null,
|};

解析:
熟悉Fiber的含义和属性含义就可以了,之后讲React更新的时候,还会提到它。

GitHub:
https://github.com/AttackXiaoJinJin/reactExplain/blob/master/react16.8.6/packages/react-reconciler/src/ReactFiber.js

三、总结
(1)Fiber的三个作用
(2)单向遍历
(3)props.children连接
(4)子指父
(5)doubleBuffer

(完)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/110000.html

相关文章

  • react解析: render的FiberRoot(三)

    摘要:查看创建核心函数源码行调用函数创建是相关,不用管源码行这个指的是调用创建,下面我们将会说到对象源码行源码行函数中,首先创建了一个,然后又创建了一个,它们两者还是相互引用。 感谢 yck: 剖析 React 源码解析,本篇文章是在读完他的文章的基础上,将他的文章进行拆解和加工,加入我自己的一下理解和例子,便于大家理解。觉得yck写的真的很棒 。React 版本为 16.8.6,关于源码的...

    muddyway 评论0 收藏0
  • React源码解析ReactDOM.render()

    摘要:一更新的方式有三种渲染接下来,我们就来看下源码二作用在提供的里渲染一个元素,并返回对该组件的引用常见的用法是这个官网网址源码服务端使用方法渲染节点是让服务端尽可能复用节点,提高性能元素容器应用渲染结束后,调用的函数错误抓取方法本质是返回 showImg(https://segmentfault.com/img/remote/1460000020064414?w=1240&h=641);...

    iKcamp 评论0 收藏0
  • React源码解析(一)

    摘要:是整个应用的起点,包含应用挂载的目标节点,记录整个应用更新过程的各种信息是一个对象是当前应用对应的对象,即。每个节点会对应一个对象,记录节点的各种状态,比如,,这些状态更新完成后会被更新,是所对应节点的实际的实例,比如对应一个就是一个。 ReactDom.render做了什么 首先react代码分为react和react-dom两个包,react中代码量特别的少,基本就是API的定义,...

    zzbo 评论0 收藏0
  • 剖析 React 源码:render 流程(一)

    摘要:大家可以看到是构造函数构造出来的,并且内部有一个对象,这个对象是本文接下来要重点介绍的对象,接下来我们就来一窥究竟吧。在构造函数内部就进行了一步操作,那就是创建了一个对象,并挂载到了上。下一篇文章还是流程相关的内容。这是我的剖析 React 源码的第二篇文章,如果你没有阅读过之前的文章,请务必先阅读一下 第一篇文章 中提到的一些注意事项,能帮助你更好地阅读源码。 文章相关资料 React ...

    hiYoHoo 评论0 收藏0
  • 浅谈React Fiber

    摘要:因为版本将真正废弃这三生命周期到目前为止,的渲染机制遵循同步渲染首次渲染,更新时更新时卸载时期间每个周期函数各司其职,输入输出都是可预测,一路下来很顺畅。通过进一步观察可以发现,预废弃的三个生命周期函数都发生在虚拟的构建期间,也就是之前。 showImg(https://segmentfault.com/img/bVbweoj?w=559&h=300); 背景 前段时间准备前端招聘事项...

    izhuhaodev 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<