React16_Fiber
Fiber是什么
可简单认为是,以链表结构相连的 虚拟DOM,同时挂载了 组件状态和更新操作
一种架构名称 : React16的Reconciler基于Fiber节点实现,被称为Fiber Reconciler。
React15的Reconciler采用递归的方式执行,数据保存在递归调用栈中,所以被称为stack Reconciler。
一种数据结构名称 : 一个Fiber节点对应一个React element,包含组件的类型,虚拟DOM、真实DOM等信息。
React的最小工作单元 : 运行时,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存在两颗Fiber树,当前页面内容对应的 current Fiber树
, 内存中构建的 workInProgress Fiber树
workInProgress Fiber树
构建完成交给Renderer渲染,
应用根节点的current指针指向workInProgress Fiber树
,workInProgress Fiber树
就变为current Fiber树
。
每次状态更新都会产生新的workInProgress Fiber树
,通过current与workInProgress的替换,完成DOM更新。
在内存中构建树,可随时终止更新,让渡浏览器主线程,构建完毕一次性commit渲染视图
current Fiber树
节点为 current fiber,workInProgress Fiber树
节点为 workInProgress fiber,他们通过alternate属性连接。
currentFiber.alternate === workInProgressFiber;
workInProgressFiber.alternate === currentFiber;
mount 与 update 流程
mount时,
ReactDOM.render 会创建 fiberRoot
应用根节点,其 current 指向 当前页面内容对应的 current Fiber树
.
render阶段,在内存中 依组件次序 各自创建 虚拟DOM转换为 Fiber,连接构成Fiber树,此时为 workInProgress Fiber树
.
render阶段,构建 workInProgress Fiber树
时会尝试复用 current Fiber树
中已有的Fiber节点内的属性.
commit阶段, workInProgress Fiber树
渲染到页面,FiberRootNode.current
指向其,使其变成 current Fiber 树
.
update时,
点击触发状态改变,这会 开启一次新的render阶段并构建一棵新的workInProgress Fiber 树
。
与 mount时 一样,render阶段,尝试复用,完成构建进入commit阶段完成渲染,current Fiber 树
再次变更.
Fiber的工作原理(Fiber节点篇)
didReceiveUpdate = false
代表无法复用之前的Fiber,直接创建新Fiber替换
在mount时只有rootFiber会赋值Placement effectTag,在commit阶段只会执行一次插入操作,
换句话说,父节点无法复用,则所有子节点都会重新创建,不考虑复用。
JSX是什么
JSX 是一种语法糖,就像 async函数是Promise的语法糖.
babel对JSX语法进行正则匹配,通过AST语法树,将JSX代码替换为了
React.createElement()
React.createElement()
运行时的返回值就是 虚拟DOM,也是 ReactElement组件 mount 时, Reconciler 将 虚拟DOM 生成 Fiber节点
JSX => React.createElement()
=> 虚拟DOM => Fiber
React17开始将JSX库单独提出,以便其他库使用JSX语法,而可以不引入React,
React.createElement()
变成了jsx()
其他
回头再补:React18以前会EffectList(副作用链)收集副作用,React18.2没有effect了。现在从根节点递归收集副作用
18.2用 subTreeFlags,表示子节点是否有修改,冒泡
为什么Vue不需要Fiber
Diff算法
当key不同时只代表遍历到的该fiber不能被p复用,后面还有兄弟fiber还没有遍历到。所以仅仅标记该fiber删除