functionunstable_runWithPriority(priorityLevel, eventHandler) { switch (priorityLevel) { case ImmediatePriority: case UserBlockingPriority: case NormalPriority: case LowPriority: case IdlePriority: break; default: priorityLevel = NormalPriority; }
var previousPriorityLevel = currentPriorityLevel; var previousEventStartTime = currentEventStartTime; currentPriorityLevel = priorityLevel; currentEventStartTime = getCurrentTime();
if (firstEffect !== null && rootWithPendingPassiveEffects !== null) { // This commit included a passive effect. These do not need to fire until // after the next paint. Schedule an callback to fire them in an async // event. To ensure serial execution, the callback will be flushed early if // we enter rootWithPendingPassiveEffects commit phase before then. let callback = commitPassiveEffects.bind(null, root, firstEffect); if (enableSchedulerTracing) { // TODO: Avoid this extra callback by mutating the tracing ref directly, // like we do at the beginning of commitRoot. I've opted not to do that // here because that code is still in flux. callback = Scheduler_tracing_wrap(callback); } passiveEffectCallbackHandle = runWithPriority(NormalPriority, () => { return schedulePassiveEffects(callback); }); passiveEffectCallback = callback; }
functioncommitWork(current: Fiber | null, finishedWork: Fiber): void{ if (!supportsMutation) { // 这里暂时不理解MemoComponent 略过它 switch (finishedWork.tag) { case FunctionComponent: case ForwardRef: case MemoComponent: case SimpleMemoComponent: { commitHookEffectList(UnmountMutation, MountMutation, finishedWork); return; } } commitContainer(finishedWork); return; }
switch (finishedWork.tag) { case FunctionComponent: case ForwardRef: case MemoComponent: case SimpleMemoComponent: { // 这里暂时不理解MemoComponent 略过它 commitHookEffectList(UnmountMutation, MountMutation, finishedWork); return; } case ClassComponent: { return; } case HostComponent: { const instance: Instance = finishedWork.stateNode; if (instance != null) { // Commit the work prepared earlier. const newProps = finishedWork.memoizedProps; // For hydration we reuse the update path but we treat the oldProps // as the newProps. The updatePayload will contain the real change in // this case. const oldProps = current !== null ? current.memoizedProps : newProps; const type = finishedWork.type; // TODO: Type the updateQueue to be specific to host components. const updatePayload: null | UpdatePayload = (finishedWork.updateQueue: any); finishedWork.updateQueue = null; if (updatePayload !== null) { commitUpdate( instance, updatePayload, type, oldProps, newProps, finishedWork, ); } } return; } case HostText: { // 更新文本 这里暂时略过 return; } case HostRoot: { return; } case Profiler: { return; } case SuspenseComponent: { // 错误捕获 这里略 return; } case IncompleteClassComponent: { return; } default: { } } }
functionunmountHostComponents(current): void{ // We only have the top Fiber that was deleted but we need to recurse down its // children to find all the terminal nodes. let node: Fiber = current;
// Each iteration, currentParent is populated with node's host parent if not // currentParentIsValid. let currentParentIsValid = false;
// Note: these two variables *must* always be updated together. let currentParent; let currentParentIsContainer;
while (true) { if (!currentParentIsValid) { let parent = node.return; // 向上遍历node.return, 直到node.tag对应以下三种类型的组件为止 才继续往下走 // 此时currentParentIsValid赋值为true 后面再进上一个while就不会进入此处 // 或者说 不会更新currentParent && currentParentIsContainer findParent: while (true) { switch (parent.tag) { case HostComponent: currentParent = parent.stateNode; currentParentIsContainer = false; break findParent; case HostRoot: currentParent = parent.stateNode.containerInfo; currentParentIsContainer = true; break findParent; case HostPortal: currentParent = parent.stateNode.containerInfo; currentParentIsContainer = true; break findParent; } parent = parent.return; } currentParentIsValid = true; }
if (node.tag === HostComponent || node.tag === HostText) { // HostComponent&Text直接设法移除 commitNestedUnmounts(node); // umount所有children之后,开始将node从tree中移除 if (currentParentIsContainer) { // 如果当前parent是一个容器组件 比如HostRoot&HostPortal removeChildFromContainer( // 这个函数几类于: currentParent.removeChild(node.stateNode) 但是多了个注释节点的处理 ((currentParent: any): Container), (node.stateNode: Instance | TextInstance), ); } else { // 如果是另外一个HostComponent(原ReactDomComponent) removeChild( // 等同:currentParent.removeChild(node.stateNode) ((currentParent: any): Instance), (node.stateNode: Instance | TextInstance), ); } // Don't visit children because we already visited them. } elseif ( enableSuspenseServerRenderer && node.tag === DehydratedSuspenseComponent ) { // 服务端渲染 这里不管 略过 } elseif (node.tag === HostPortal) { // 递归HostPortal 对其脱壳处理 转换成普通组件处理 if (node.child !== null) { // When we go into a portal, it becomes the parent to remove from. // We will reassign it back when we pop the portal on the way up. currentParent = node.stateNode.containerInfo; currentParentIsContainer = true; // Visit children because portals might contain host components. node.child.return = node; node = node.child; continue; } } else { // 遇到FunctionComponent|ClassComponent什么的直接卸载 commitUnmount(node); // 递归node.child if (node.child !== null) { node.child.return = node; node = node.child; continue; } } // 以下都是遍历Fiber树需要的代码 if (node === current) { return; } while (node.sibling === null) { if (node.return === null || node.return === current) { return; } node = node.return; if (node.tag === HostPortal) { // When we go out of the portal, we need to restore the parent. // Since we don't keep a stack of them, we will search for it. currentParentIsValid = false; } } node.sibling.return = node.return; node = node.sibling; } }