对于Fiber我们可以理解为存储在内存中的Dom
对于React15在render阶段的reconcile是不可打断的,如果在操作大量的dom时,会存在卡顿,因为浏览器将所有的时间都交给了js引擎线程去执行,此时GUI渲染线程被阻塞,导致页面出现卡顿,无法响应用户对应的事件。
所以在React16之后就有了Scheduler来进行时间片的调度,给每一个task一定的时间,如果在这个时间内没有执行完,也要交出执行权给浏览器进行绘制和重排,所以异步可中断的更新需要一定的数据结构在内存中保存dom信息,所以产出了这样一种数据结构Fiber,也可以称为虚拟Dom。
Fiber数据结构
function FiberNode(
tag: WorkTag,
pendingProps: mixed,
key: null | string,
mode: TypeOfMode,
) {
//保存节点的信息
this.tag = tag;//对应组件的类型
this.key = key;//key属性
this.elementType = null;//元素类型
this.type = null;//func或者class
this.stateNode = null;//真实dom节点
//连接成fiber树
this.return = null;//指向父节点
this.child = null;//指向child
this.sibling = null;//指向兄弟节点
this.index = 0;
this.ref = null;
//用来计算state
this.pendingProps = pendingProps;
this.memoizedProps = null;
this.updateQueue = null;
this.memoizedState = null;
this.dependencies = null;
this.mode = mode;
//effect相关
this.effectTag = NoEffect;
this.nextEffect = null;
this.firstEffect = null;
this.lastEffect = null;
//优先级相关的属性
this.lanes = NoLanes;
this.childLanes = NoLanes;
//current和workInProgress的指针
this.alternate = null;
}
Fiber双缓存
对于上述的讲解,我们知道了Fiber可以保存真实的dom,在mount的时候会先将jsx对象构建Fiber对象,形成Fiber树,这颗Fiber树叫做current Fiber并对应到真实Dom上。而正在构建的Fiber树叫做workInProgress Fiber,两棵树的节点会通过alternate相连。
对于这样的Dom结构会生成如下的Fiber
function App() {
return (
zi
bai
)
}
ReactDOM.render(, document.getElementById(“root”));
对于上述结构的Fiber图如下:

mount
在Mount时候只会创建FiberRoot和rootFiber两个节点,对于fiberRoot是指整个应用的根节点,只存在一个。对于rootFiber是指ReactDom.render或者ReactDOM.unstable_createRoot所创建出来的节点,可以存在多个。初始时如下:
然后根据jsx创建workInProgress Fiber,然后通过alternate链接
接着workInProgress Fiber会和current Fiber交换位置,此时workInProgress变为current Fiber并渲染成对应的真实Dom则为如下图:
update
在update时会根据状态变更后的jsx对象和current Fiber做对比形成新的workInProgress Fiber,然后workInProgress Fiber切换成current Fiber应用到真实dom就达到了更新的目的,而这一切都是在内存中发生的,从而减少了对dom好性能的操作。
最后再把workInProgress Fiber切换为current Fiber
上述为update时,current Fiber与workInProgress Fiber的变化