Open 1mikasa1 opened 2 years ago
function requestUpdateLane(fiber) { // 获取到当前渲染的模式:sync mode(同步模式) 或 concurrent mode(并发模式) var mode = fiber.mode; // 是否为并发模式 if ((mode & ConcurrentMode) === NoMode) { return SyncLane; } else if ( (executionContext & RenderContext) !== NoContext && // workInProgressRootRenderLanes为当前需要更新的fiber的lane值,并且当有更新任务时,该值不为空,同时返回该lane workInProgressRootRenderLanes !== NoLanes ) { return pickArbitraryLane(workInProgressRootRenderLanes); } // todo 检查当前事件是否是过渡优先级, 是则返回一个过渡优先级 var isTransition = requestCurrentTransition() !== NoTransition; if (isTransition) { if ( ReactCurrentBatchConfig$3.transition !== null) { var transition = ReactCurrentBatchConfig$3.transition; if (!transition._updatedFibers) { transition._updatedFibers = new Set(); } transition._updatedFibers.add(fiber); } if (currentEventTransitionLane === NoLane) { // All transitions within the same event are assigned the same lane. currentEventTransitionLane = claimNextTransitionLane(); } return currentEventTransitionLane; } // 当触发react内部的事件时,会调用dispatchDiscreteEvent,更新currentUpdatePriority,这里就是直接来拿到这个变量值 var updateLane = getCurrentUpdatePriority(); if (updateLane !== NoLane) { return updateLane; } // 在react的外部事件中触发的更新事件,触发时为当前事件设置一个优先级 var eventLane = getCurrentEventPriority(); return eventLane; }
// 在更新队列的队尾插入update function enqueueUpdate(fiber, update, lane) { // 在createRoot时生成并挂载到了rootFiber下 var updateQueue = fiber.updateQueue; if (updateQueue === null) { // Only occurs if the fiber has been unmounted. return; } var sharedQueue = updateQueue.shared; if (isInterleavedUpdate(fiber)) { ... } else { // 队列最后一个upate var pending = sharedQueue.pending; // 如果没有则直接作为第一个 if (pending === null) { // This is the first update. Create a circular list. update.next = update; } else { // 队尾的upate.next字段指向他的前一个upate update.next = pending.next; // 更新pending.next,让其始终指向队列的最后一个uptate pending.next = update; } // pending指向队列最后一个update sharedQueue.pending = update; } }
function scheduleUpdateOnFiber(fiber, lane, eventTime) {
console.log('workInProgressRoot', workInProgressRoot)
// 判断是否是无限嵌套的update队列,例如render函数里面放setState,
checkForNestedUpdates();
// 更新事件优先级,rootFiber更新lanes,子fiber树更新childlanes
var root = markUpdateLaneFromFiberToRoot(fiber, lane);
// 更新fiberRootNode的pendingLanes
markRootUpdated(root, lane, eventTime);
if ((executionContext & RenderContext) !== NoLanes && root === workInProgressRoot) {
warnAboutRenderPhaseUpdatesInDEV(fiber); // Track lanes that were updated during the render phase
} else {
// This is a normal update, scheduled from outside the render phase. For
// example, during an input event.
{
if (isDevToolsPresent) {
addFiberToLanesMap(root, fiber, lane);
}
}
warnIfUpdatesNotWrappedWithActDEV(fiber);
if (root === workInProgressRoot) {
// TODO: Consolidate with isInterleavedUpdate
check
// Received an update to a tree that's in the middle of rendering. Mark
// that there was an interleaved update work on this root. Unless the
// deferRenderPhaseUpdateToNextBatch
flag is off and this is a render
// phase update. In that case, we don't treat render phase updates as if
// they were interleaved, for backwards compat reasons.
if ( (executionContext & RenderContext) === NoContext) {
workInProgressRootInterleavedUpdatedLanes = mergeLanes(workInProgressRootInterleavedUpdatedLanes, lane);
}
if (workInProgressRootExitStatus === RootSuspendedWithDelay) {
// The root already suspended with a delay, which means this render
// definitely won't finish. Since we have a new update, let's mark it as
// suspended now, right before marking the incoming update. This has the
// effect of interrupting the current render and switching to the update.
// TODO: Make sure this doesn't override pings that happen while we've
// already started rendering.
markRootSuspended$1(root, workInProgressRootRenderLanes);
}
}
// 这里
ensureRootIsScheduled(root, eventTime);
if (lane === SyncLane && executionContext === NoContext && (fiber.mode & ConcurrentMode) === NoMode && // Treat act
as if it's inside batchedUpdates
, even in legacy mode.
!( ReactCurrentActQueue$1.isBatchingLegacy)) {
resetRenderTimer();
flushSyncCallbacksOnlyInLegacyMode();
}
}
return root; }
function ensureRootIsScheduled(root, currentTime) { // 旧任务 var existingCallbackNode = root.callbackNode; // Check if any lanes are being starved by other work. If so, mark them as markStarvedLanesAsExpired(root, currentTime); // Determine the next lanes to work on, and their priority. // 获取renderLanes。与update.lane有关,但不相同,update.lane是事件的优先级。 var nextLanes = getNextLanes(root, root === workInProgressRoot ? workInProgressRootRenderLanes : NoLanes); ...
// 任务优先级,即renderLanes对应的lanePriority。 var newCallbackPriority = getHighestPriorityLane(nextLanes); // Check if there's an existing task. We may be able to reuse it. var existingCallbackPriority = root.callbackPriority; // 比较新旧任务优先级,判断是否有必要发起一次新调度 if (existingCallbackPriority === newCallbackPriority && !( ReactCurrentActQueue$1.current !== null && existingCallbackNode !== fakeActCallbackNode)) { { ... } return; }
// 如果存在旧任务,那么看一下能否复用 if (existingCallbackNode != null) { cancelCallback$1(existingCallbackNode); }
// 调度一个新任务 var newCallbackNode; // 若新任务的优先级为同步优先级,则同步调度,传统的同步渲染和过期任务会走这里 if (newCallbackPriority === SyncLane) { if (root.tag === LegacyRoot) { if ( ReactCurrentActQueue$1.isBatchingLegacy !== null) { ReactCurrentActQueue$1.didScheduleLegacyUpdate = true; } scheduleLegacySyncCallback(performSyncWorkOnRoot.bind(null, root)); } else { scheduleSyncCallback(performSyncWorkOnRoot.bind(null, root)); } { if ( ReactCurrentActQueue$1.current !== null) { ReactCurrentActQueue$1.current.push(flushSyncCallbacks); } else { scheduleMicrotask(function () { if (executionContext === NoContext) { flushSyncCallbacks(); } }); } } newCallbackNode = null; } else { var schedulerPriorityLevel; // 获取调度优先级 switch (lanesToEventPriority(nextLanes)) { ... } newCallbackNode = scheduleCallback$1(schedulerPriorityLevel, performConcurrentWorkOnRoot.bind(null, root)); } root.callbackPriority = newCallbackPriority; root.callbackNode = newCallbackNode; }
// 在原型上添加render方法 ReactDOMHydrationRoot.prototype.render = ReactDOMRoot.prototype.render = function (children) { // rootFiberNode实例 var root = this._internalRoot;
if (root === null) { throw new Error('Cannot update an unmounted root.'); }
{ // ... // root绑定的dom元素 var container = root.containerInfo; // ... } } updateContainer(children, root, null, null); };
/**
// 创建一个update var update = createUpdate(eventTime, lane); // Caution: React DevTools currently depends on this property // being called "element". update.payload = { element: element }; callback = callback === undefined ? null : callback; if (callback !== null) { { if (typeof callback !== 'function') { error('render(...): Expected the last optional
callback
argument to be a ' + 'function. Instead received: %s.', callback); } } update.callback = callback; } // 将update插入到rootFiber下更新队列的队尾 enqueueUpdate(current$1, update); // 开始调度 var root = scheduleUpdateOnFiber(current$1, lane, eventTime); if (root !== null) { entangleTransitions(root, current$1, lane); } return lane; }