Reconciler(协调器)是render阶段的 第二个阶段的工作,整个工作的过程可以分为 递和归
- 递: beginWork
- 归: completeWork
<div>
<span>1</span>
<ul>
<li>2</li>
<li>3</li>
</ul>
</div>
beginWork主要工作流程是根据传入的FiberNode创建下一级的FiberNode
整个beginWork工作流程图如下:
首先在beginWork中,会判断当前的流程是 mount ,还是 update,判断的依据是根据 currentFiberNode 是否存在
if(current !== null){
// update
} else {
// mount
}
如果是update, 接下来会判断 wipFiberNode 是否能够复用,如果不能够复用,那么 update 和 mount 的流程基本是一样的
- 根据 wip.tag 进行不同的分支处理
- 根据 reconcile 算法生成下一级的FiberNode (diff算法)
- 无法复用的update 流程 和 mount 流程基本一样,主要区别在于是否会生成带flags 的 FiberNode
/**
*
* @param {*} current currentFiberNode
* @param {*} workInProgress wip 正在内存构建的
* @param {*} renderLanes lanes
*/
function beginWork(current, workInProgress, renderLanes){
if(current !== null){
// 更新
} else {
// mount
}
switch(workInProgress.tag){
case IndeterminateComponent:{
}
case FunctionComponent: {
}
case ClassComponent: {
}
}
}
关于tag,在源码里面定义了28种:
const FunctionComponent = 0
const ClassComponent = 1
const HostRoot = 3
const HostText = 6
......
根据不同的tag 处理完 FiberNode之后,根据是 mount 还是 update 会进入不同的方法:
- mount: mountChildFibers
- update: reconcileChildFibers
实际上,上面两个方法都是一个叫 ChildReconciler方法的返回值
var reconcileChildFibers = ChildReconciler(true)
var mountChildFibers = ChildReconciler(false)
function ChildReconciler(shouldTrackSideEffects){
}
ChildReconciler方法中,shouldTrackSideEffects 是一个 布尔值
- false 不追踪副作用,不做flags标记
- true 追踪副作用,做flags标记
在 ChildReconciler 方法内部,就会根据 shouldTrackSideEffects 做一些不同的处理:
function placeChild(newFiber, lastPlaceIndex, newIndex){
newFiber.index = newIndex
if(!shouldTrackSideEffects){
// 初始化
newFiber.flags |= Forked
return lastPlaceIndex
}
// 更新
newFiber.flags |= Placement
}
可以看到,在beginWork方法内部,也会做一些 flags标记,这些 flags 标记主要和元素的位置有关系
- 标记 ChildDeletion 代表删除操作
- 标记 Placement 代表插入或者移动操作