React
设计体系如人类社会一般,拨动时间轮盘的那一刻,你便成了穿梭在轮片中的一粒细沙,角逐过程处处都需要亮出你的属性,你重要吗?你无可替代吗?你有特殊权限吗?没有,那不好意思,请继续在轮片中循环。属于你的生命之火殆尽,前来悼念之人很多,这幕,像极了出生时的场景。
干啥玩意儿,这是技术文章不是抒情散文!下面进入正题。
创建的准备上一节已经说明了,主要定义与更新相关的数据结构和变量,计算过期时间等。完成这些准备工作之后,正式进入调度工作,调度过程实现思路是:当与更新或挂载相关api被调用时,就会执行更新的逻辑,更新大致分为以下几个小阶段
scheduleWork
该步骤的主要工作有以下几点
- 通过
scheduleWorkOnParentPath
方法找到当前Fiber
的root节点 - 遍历当前更新节点父节点上的每个节点,对比每个节点的
expirationTime
,如果大于当前节点,则将其值赋值为当前节点的expirationTime
值。同时,childExpirationTime
的值也是该的逻辑
export function scheduleUpdateOnFiber(
fiber: Fiber,
expirationTime: ExpirationTime,
) {
checkForNestedUpdates();
warnAboutInvalidUpdatesOnClassComponentsInDEV(fiber);
const root = markUpdateTimeFromFiberToRoot(fiber, expirationTime);
if (root === null) {
warnAboutUpdateOnUnmountedFiberInDEV(fiber);
return;
}
checkForInterruption(fiber, expirationTime);
recordScheduleUpdate();
// TODO: computeExpirationForFiber also reads the priority. Pass the
// priority as an argument to that function and this one.
const priorityLevel = getCurrentPriorityLevel();
if (expirationTime === Sync) {
if (
// Check if we're inside unbatchedUpdates
(executionContext & LegacyUnbatchedContext) !== NoContext &&
// Check if we're not already rendering
(executionContext & (RenderContext | CommitContext)) === NoContext
) {
// Register pending interactions on the root to avoid losing traced interaction data.
schedulePendingInteractions(root, expirationTime);
performSyncWorkOnRoot(root);
} else {
ensureRootIsScheduled(root);
schedulePendingInteractions(root, expirationTime);
if (executionContext === NoContext) {
flushSyncCallbackQueue();
}
}
} else {
ensureRootIsScheduled(root);
schedulePendingInteractions(root, expirationTime);
}
...
}
export const scheduleWork = scheduleUpdateOnFiber;
如果过期时间等于我们定义的Sync常量对应值,则进一步判断这次更新的状态,如果不是 batchUpdates
什么时候不是这个状态呢?我们前面认识过,比如reder时,判断完这个状态后还需要保证这次的更新渲染已准备好,则开始处理。不过处理之前,还要进行一个操作就是pending interaction,与我们动作相关的内容数据需要保存于 pendingInteractionMap
中。
相关参考视频讲解:进入学习
function scheduleInteractions(root, expirationTime, interactions) {
if (!enableSchedulerTracing) {
return;
}
if (interactions.size > 0) {
const pendingInteractionMap = root.pendingInteractionMap;
const pendingInteractions = pendingInteractionMap.get(expirationTime);
if (pendingInteractions != null) {
interactions.forEach(interaction => {
if (!pendingInteractions.has(interaction)) {
// Update the pending async work count for previously unscheduled interaction.
interaction.__count++;
}