美文网首页
Render 阶段

Render 阶段

作者: bestCindy | 来源:发表于2022-04-12 20:22 被阅读0次

在 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

相关文章

网友评论

      本文标题:Render 阶段

      本文链接:https://www.haomeiwen.com/subject/hfxbsrtx.html