Fiber可以解决哪些事
工作单元、任务分解: Fiber最重要的功能就是作为工作单元,保存原生节点或组件节点对应信息(包括优先级),这些节点通过指针的形式形成Fiber树增量更新:通过jsx对象和current Fiber的对比,生成最小的差异补丁(也就是新增的部分),应用到真实节点上根据优先级暂停、继续、排列优先级:Fiber节点上保存了优先级,能通过不同节点优先级的对比,达到任务的暂停、继续、排列优先级等能力,也为上层实现批量更新、Suspense提供了基础保存状态: 因为Fiber能保存状态和更新的信息,所以就能实现函数组件的状态更新,也就是hooks
Fiber的数据结构
FiberNode函数:因为版本不同,和下面的有点出入
Fiber的自带属性如下:
//ReactFiber.old.js
function FiberNode(
tag: WorkTag,
pendingProps: mixed,
key: null | string,
mode: TypeOfMode,
) {
//作为静态的数据结构 保存节点的信息
this.tag = tag;// 对应组件的类型
this.key = key;//key属性
this.elementType = null;// 元素类型。react的elementType,就是 REACT_ELEMENT_TYPE
this.type = null;//class、func、div字符串等
this.stateNode = null;// 指向真实的dom节点,或者根节点指向FiberRootNode
//作为fiber数架构 连接成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;// 存放未计算的update
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双缓存
Fiber可以保存真实的dom,真实dom对应在内存中的Fiber节点会形成Fiber树,这颗Fiber树在React中叫current Fiber。也就是当前dom对应的Fiber树,而正在构建的Fiber树叫workInProgress Fiber,这两棵树的节点通过alternate相连
上面有提到workInProgress Fiber,创建workInProgress Fiber发生在createWorkInProgress()函数中,会创建或复用Fiber
修改current Fiber的指向,是通过修改FiberRootNode.current来进行切换
// ReactFiberWorkLoop.old.js
root.current = finishedWork;
mount
第一次渲染时,会创建 fiberRoot 和 rootFiber,然后根据jsx对象创建Fiber节点,节点连接成current Fiber树
该阶段流程分3步
- 第一步:刚开始只创建了fiberRoot和rootFiber两个节点
- 第二步:根据jsx创建workInProgress Fiber
- 第三步:把workInProgress Fiber切换成current Fiber
update
update分为2步
- 第一步:根据current Fiber创建workProgress Fiber
- 第二步:把workInProgress Fiber切换成current Fiber
Q & A
函数组件为什么能保存状态?
- 状态并不是保存在函数组件里面,而是保存在Fiber身上
- Fiber身上有
updateQueue,可以通过循环updateQueque计算新的状态
为什么可以实现中断和继续?
因为中断的时候会保存下一个Fiber,恢复的时候,会拿到这个所谓的下一个Fiber,继续遍历