在 React 中,协调器执行的阶段称作 render 阶段,渲染器执行的阶段称做 commit 阶段
在 render 阶段中,如果是同步更新的,会调用 performSyncWorkOnRoot ,在这个方法中会调用 workLoopSync
function workLoopSync() {
// Already timed out, so perform work without checking if we need to yield.
while (workInProgress !== null) {
performUnitOfWork(workInProgress);
}
}
performUnitOfWork 的作用是:
- 创建下一个 Fiber 节点并赋值给
workInProgress - 将
workInProgress与已创建的 Fiber 节点连起来构成 Fiber 树
创建 Fiber 树的过程相当于一个深度优先遍历,是一个递归的过程,递的过程是 beginWork,归的过程是 completeWork
beginWork
// current : 上一次更新对应的 Fiber 节点,workInProcess.alternate
// workInProgress : 当前的 Fiber 节点
// renderLanes : 优先级相关
function beginWork(current, workInProgress, renderLanes) { ... }
beginWork 会根据 current !== null 判断当前处于 mount 阶段还是 update 阶段
update 情况下
会判断是否可以复用之前的 fiber,如果可以复用,会调用 attemptEarlyBailoutIfNoScheduledUpdate --> bailoutOnAlreadyFinishedWork 复用之前的 Fiber 然后 return 掉
mount 的情况下,和节点不能复用的情况下
mount 时会根据不同的 fiber.tag 新建子 Fiber
switch (workInProgress.tag) {
case tag1:
case tag2:
//...
}
对于 FunctionComponent,ClassComponent,HostComponent,会调用reconcileChildren 方法,这个方法是 Reconciler 核心的方法
在这个方法中,会根据 current === null 是 mount 还是 update
- mount:创建新的 Fiber node
- update:进行 Differ 算法,比较结果生成带 effectTag 的子 Fiber 节点
function reconcileChildren(current, workInProgress, nextChildren, renderLanes) {
if (current === null) {
workInProgress.child = mountChildFibers(workInProgress, null, nextChildren, renderLanes);
} else {
workInProgress.child = reconcileChildFibers(workInProgress, current.child, nextChildren, renderLanes);
}
}
effectTag
render 阶段是在内存中进行的,工作结束后会通知 Renderer,Rendener 根据fiber.effectTag 执行的 Dom 操作
completeWork
completeWork 也是针对不同的 fiber 调用不同的处理逻辑
其中 HostCompoment 是原生 DOM 组件对应的 Fiber 节点
在处理 HostComponent 的逻辑中,会通过 current == null 判断是 mount 还是 update
通过 workInProcess.stateNode != null 判断该 Fiber 节点是否存在对应的 DOM 节点
update 的情况
不需要生成 DOM 节点,主要是处理 props
只要是调用 updateHostComponent 处理
在 updateHostComponent 中会把处理完的 props 赋值给 workInProgress.updateQueue,最后在 commit阶段 渲染在页面上
mount 或者没有 stateNode 时
大概三个步骤
-
createInstance:为 Fiber 节点创建对应的 DOM 节点 -
appendAllChildren将 children 插入到刚生成的 DOM 节点中 -
finalizeInitialChildren处理 props
effectTag
每个执行完 completeWork 且存在 effectTag 的 Fiber 节点会保存在一条称为 effectList 的单向链表中
在 commit 阶段便利 effectList 就能执行所有的 effect 了












网友评论