最近在努力研究React源码,计原发现它并没有我之前想象的理藏那么难理解。
虽然源码里面有一些概念就像一座五指山困住了桀骜不驯的码里孙悟空。
但如果你理解了下面的干货满满几个概念,读懂react源码就不是设山难事了。
我们已经知道从v16.8开始,计原React进入了fiber架构时代,理藏将不可中断的码里递归改进为可中断的递归。
fiber架构主要的工作是创建fiber tree,然后在合适的时机将这棵树渲染在屏幕上.
所以围绕着fiber,源码里出现了一堆带着fiber的变量。
首先,在源码中,FiberNode是个构造函数,它包含了许多属性。
function FiberNode( this: $FlowFixMe, tag: WorkTag, pendingProps: mixed, key: null | string, mode: TypeOfMode,) { // Instance this.tag = tag; this.key = key; this.elementType = null; this.type = null; this.stateNode = null; // Fiber this.return = null; this.child = null; this.sibling = null; this.index = 0; this.ref = null; this.refCleanup = null; this.pendingProps = pendingProps; this.memoizedProps = null; this.updateQueue = null; this.memoizedState = null; this.dependencies = null; this.mode = mode; // Effects this.flags = NoFlags; this.subtreeFlags = NoFlags; this.deletions = null; this.lanes = NoLanes; this.childLanes = NoLanes; this.alternate = null;}
这些属性可以根据FiberNode的不同身份进行划分。
FiberNode在React中通常有三种不同的身份:
作为架构的一环,多个FiberNode作为基本节点构成fiber tree。
此时,它的相关属性如下:
// Fiber// 指向父节点this.return = null;// 指向第一个子节点this.child = null;// 指向右边兄弟节点this.sibling = null;this.index = 0;
作为数据的一环,它保存了基本的React元素信息。
// Instance// 对应组件的类型,可以是class、function等this.tag = tag;// 组件的keythis.key = key;// 和type类似的属性this.elementType = null;// 根据tag的不同,可以是calss、function、tagName(div、input等原始的标签)this.type = null;// FiberNode对应的元素this.stateNode = null;
这里说明一下React元素:
React元素可以是<div>Hello!</div>基本HTML元素,也可以是<App />这样的组件,App是个类组件或者函数组件等。
作为调度的一环,它提供了调度时的一些依据。
// render相关this.flags = NoFlags;this.subtreeFlags = NoFlags;this.deletions = null;// 优先级相关this.lanes = NoLanes;this.childLanes = NoLanes;// 缓存相关this.alternate = null;
前面说过,FiberNode是fiber tree最小单元。而React元素被编译之后的VNode都成为FiberNode构造函数的实例,源码中实例都用fiber或者workInProgress表示。
HostRootFiber是源码里使用createHostRootFiber创建的Fiber根节点,它包含整棵组件树的信息。对应的是如下代码:
<body> <div id="app"></div> <div id="app2"></div> <div id="app3"></div></body>
React允许你创建最多个HostRootFiber,也就是说,你可以有多个上述的挂载节点。
源码里通过createHostRootFiber的实例在作为参数时,偶尔也会使用rootFiber表示。
FiberRootNode表示应用根节点。它保存着应用的状态信息和组件信息。它的数据结构如下:
function FiberRootNode( this: $FlowFixMe, containerInfo: any, // $FlowFixMe[missing-local-annot] tag, hydrate: any, identifierPrefix: any, onRecoverableError: any,) { this.tag = tag; // 表示应用程序的容器元素,即组件树的根节点 // 它一般是一个 DOM 元素,用来承载整个组件树的渲染结果。 this.containerInfo = containerInfo; // 表示当前应用程序中待处理的子树列表 this.pendingChildren = null; // 表示当前渲染的 Fiber 树的根节点,指向 HootRootFiber this.current = null; // 网络请求优化用的属性 this.pingCache = null; // 表示最近一次渲染完成的 Fiber 树的根节点 // React 在进行组件更新时,会创建一个新的 Fiber 树 // 并将它与旧的 Fiber 树进行比较,找出需要更新的部分 // 然后进行更新。当更新完成后,最近一次渲染的结果 // 会存储在 `finishedWork` 属性中 this.finishedWork = null; // 表示当前应用程序的上下文 this.context = null; // 表示当前应用程序的挂起上下文 // 在 React 中,当组件的上下文发生变化时, // React 会将新的上下文信息存储在 `pendingContext` 中 // 待下一次更新时再进行处理。 this.pendingContext = null; // 当组件完成更新后的回调函数 this.callbackNode = null; // 表示下一次更新的过期时间 this.expirationTimes = createLaneMap(NoTimestamp); // 优先级相关的属性 this.pendingLanes = NoLanes; this.suspendedLanes = NoLanes; this.pingedLanes = NoLanes; this.expiredLanes = NoLanes; this.mutableReadLanes = NoLanes; this.finishedLanes = NoLanes; //....}
通常状况下,FiberRootNode和HootRootFiber是一一对应的关系。
FiberRootNode是单例对象,每个应用程序只会有一个实例,如果一个页面有多个React应用,那么会有多个实例。
fiberRootNode是createFiberRoot的返回值类型。即FiberRootNode实例。源码里用fiberRoot表示。
在Fiber架构中,FiberNode实例fiber既是fiber tree的基本数据结构单元,记录元素节点的信息,也是组件根节点的数据单元,记录整个组件树的信息,同时也会为调度相关的工作提供依据;
FiberRootNode的实例fiberRoot是应用根节点的数据单元,包含整个应用的状态信息和租价信息。它和HootRootFiber实例rootFiber是一一对应关系。
责任编辑:武晓燕 来源: 萌萌哒草头将军 Fiber架构数据(责任编辑:休闲)
年内北向资金净流入超1880亿元 外资持有A股市值占流通市值比4.63%
文投控股(600715.SH):北京文创定增基金已减持17.89万股 占公司总股份的0.0096%
广西铁投成功注册55亿元债务融资工具 实现在资本市场直接融资新突破
四川宜宾:打通农民工服务“最后一米” 全面推动地方产业发展提速增效
上海机场股票代码 在向sec递交的预约挂号备案文档中 什么时候展现有起色?