Fiber的含义
Fiber有三层含义
- 作为静态数据结构,每个Fiber节点对应一个React Element, 存储了组件类型(函数组件、类组件、原生组件)、以及dom的信息等。
- 做为动态工作单元,Fiber节点是每次循环执行的一个节点,在节点上会存储节点的更新信息(增、删、更新)
- 作为一种架构,所有的Fiber节点会建立父子兄弟节点之间的关联,形成一个Fiber树,React16中的Reconciler 协调器工作就是基于Fiber节点实现, 所以又叫Fiber Reconciler。
Fiber节点包含的属性
function FiberNode(
tag: WorkTag,
pendingProps: mixed,
key: null | string,
mode: TypeOfMode,
) {
// 作为静态数据结构的属性
this.tag = tag;
this.key = key;
this.elementType = null;
this.type = null;
this.stateNode = null;
// 用于连接其他Fiber节点形成Fiber树
this.return = null;
this.child = null;
this.sibling = null;
this.index = 0;
this.ref = null;
// 作为动态的工作单元的属性
this.pendingProps = pendingProps;
this.memoizedProps = null;
this.updateQueue = null;
this.memoizedState = null;
this.dependencies = null;
this.mode = mode;
this.effectTag = NoEffect;
this.nextEffect = null;
this.firstEffect = null;
this.lastEffect = null;
// 调度优先级相关
this.lanes = NoLanes;
this.childLanes = NoLanes;
// 指向该fiber在另一次更新时对应的fiber
this.alternate = null;
}
Fiber节点如何组织为一颗Fiber树
每个Fiber节点都对应着一个React Element,Fiber节点有三个属性
this.return = null; //指向父节点
this.child = null; // 指向子节点
this.sibling = null; // 指向兄弟节点
所以如下的一个JSX结构生成相应Fiber
function App() {
return (
<div>
i am
<span>KaSong</span>
</div>
)
}
对应Fiber结构
Fiber结构的工作原理
React采用“双缓存”的技术来创建和更新Fiber树,对应着DOM树的创建与更新。React应用最多会存在2颗Fiber树,一个叫current Fiber树, 代表的是当前页面对应的一个Fiber树, 一个叫workInProgress树,代表的是当前的一个构建树(更新重新构建)。
current Fiber树的的节点叫current Fiber节点, workInprogress Fiber树中的节点叫workInProgress Fiber节点,两者通过alternate相连。
React在应用中会创建一个唯一的FiberRootNode节点,即在第一次调用ReactDom.render时创建, 同时每次使用用ReactDom.render创建一个React App时会生成一个rootFiber节点(相当于是挂载的container节点对应的Fiber节点),React应用的根节点FiberRootNode有个current指针指向当前的current Fiber 树, 当应用更新生成了一颗新的workInProgress Fiber树, 并且完成了commit,更新页面dom后,会将current指向新生成的workInProgress Fiber树, 同时这颗树也就变成了current Fiber 树。如此循环的工作。
React在mount阶段和update阶段构建Fiber树有些区别,如下分别分析2种情况下的一个构建流程:
mount阶段
如下demo:
function App() {
const [num, add] = useState(0);
return (
<p onClick={() => add(num + 1)}>{num}</p>
)
}
ReactDOM.render(<App/>, document.getElementById('root'));
由于第一次渲染页面,所以此时的current Fiber树没有子节点,如下:
。
当执行render后,会构建workInProgress Fiber树,如下:
此时页面已经渲染完了, FiberRootNode节点的current属性要指向workInProgress Fiber 树。workInProgress Fiber 树变为current Fiber树。
update节点
更新阶段由于不是首次渲染页面,因此current Fiber 树是存在的,如上图所示, 所以页面触发更新后, 要生成一颗新的workInProgress Fiber 树, 这个过程中就会有diff算法。
将新的Fiber树渲染到页面后,又重新对FiberRootNode 的current指向更换, 如此继续循环工作。
参考文档: react.iamkasong.com/