# 阅读图解React笔记7

3 min read
Table of Contents

本文仅仅是阅读 图解 React 原理系列 的笔记,了解更多内容请查看原文链接。

概览

Fiber 树渲染阶段被称为 commit 阶段。fiberNode 阶段流程可能被打断,而 commit 阶段一旦开始就会同步执行直到完成。

整个阶段可以分为三个子阶段:

  • BeforeMutation 阶段
  • Mutation 阶段
  • Layout 阶段

CommitRoot

整个渲染逻辑都在 CommitRootImpl 函数上,其源码位置 ReactFiberWorkLoop.new.js

在 commitRoot 中同时使用到了渲染优先级和调度优先级,最后的实现是通过 commitRootImpl 函数:

function commitRootImpl(root, recoverableErrors, transitions, renderPriorityLevel) {
// ============
// 渲染前准备
// ============
const finishedWork = root.finishedWork
const lanes = root.finishedLanes
// 清空 FiberRoot 对象上的属性
root.finishedWork = null
root.finishedLanes = NoLanes
root.callbackNode = null
if (root === workInProgressRoot) {
workInProgressRoot = null
workInProgress = null
workInProgressRootRenderLanes = NoLanes
}
// ========
// 渲染
// ========
// 检查是否有副作用在整个树
const subtreeHasEffect =
(finishedWork.subtreeFlags &
(BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !==
NoFlags
const rootHasEffect =
(finishedWork.flags &
(BeforeMutationMask | MutationMask | LayoutMask | PassiveMask)) !==
NoFlags
if (subtreeHasEffect || rootHasEffect) {
const prevExecutionContext = executionContext
executionContext |= CommitContext
const prevInteractions = pushInteractions(root)
// 调用生命周期前,重置为null
ReactCurrentOwner.current = null
// 第一个阶段
commitBeforeMutationEffects(finishedWork)
// 第二个阶段
commitMutationEffects(finishedWork, root, renderPriorityLevel)
// fiber 树的切换
root.current = finishedWork
// 第三个阶段
commitLayoutEffects(finishedWork, root, lanes)
// 如果有被动的副作用,调度一个回调处理它。
if (
(finishedWork.subtreeFlags & PassiveMask) !== NoFlags ||
(finishedWork.flags & PassiveMask) !== NoFlags
) {
if (!rootDoesHavePassiveEffects) {
rootDoesHavePassiveEffects = true
scheduleCallback(NormalSchedulerPriority, () => {
flushPassiveEffecs()
return null
})
}
}
// 告知调度器在帧的末尾产生,所以浏览器能有机会绘制。
requestPaint()
// =========
// 渲染后
// =========
const rootDidHavePassiveEffects = rootDoesHavePassiveEffects
if (rootDoesHavePassiveEffects) {
// 这次 commit 有被动副作用,保存对它们的引用。
rootDoesHavePassiveEffects = false
rootWithPendingPassiveEffects = root
pendingPassiveEffectsLanes = lanes
} else {
releaseRootPooledCache(root, remainingLanes)
}
// 结束之前总是要调用该函数,确保当前 root 所有额外的工作的被调度。
ensureRootIsScheduled(root, now())
// 如果布局被调度了,刷新它
flushSyncCallbackQueue()
return null
}
}

大致可以将 commitRootImpl 划分为渲染前,渲染,渲染后。

渲染前主要是设置一些全局变量和重置一些全局状态。

渲染被划分为 3 个阶段处理实现:

  • commitBeforeMutationEffects
  • commitMutationEffects
  • recursivelyCommitLayoutEffects

渲染后主要做一些重置和清理工作。

参考链接


More Posts