在 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
了
网友评论