Mutation阶段次要做了什么

1.入口函数:commitMutationEffects()
2.筹备开始执行:commitMutationEffects_begin
3.遍历Effect链表:commitMutationEffects_complete
4.对失去的单Fibre节点进行解决:commitMutationEffectsOnFiber

commitMutationEffects

  • Mutation阶段的入口函数
export function commitMutationEffects(  root: FiberRoot,  firstChild: Fiber,  committedLanes: Lanes,) {  inProgressLanes = committedLanes;  inProgressRoot = root;  nextEffect = firstChild;  commitMutationEffects_begin(root);  inProgressLanes = null;  inProgressRoot = null;}

commitMutationEffects_begin

  • 对Effect链表遍历,且如果Fibre节点上有须要删除的child就删commitDeletion(root, childToDelete, fiber)
  • 传入单个Fiber节点给commitMutationEffects_complete解决
function commitMutationEffects_begin(root: FiberRoot) {  while (nextEffect !== null) {    const fiber = nextEffect;    // TODO: Should wrap this in flags check, too, as optimization    const deletions = fiber.deletions;    if (deletions !== null) {      for (let i = 0; i < deletions.length; i++) {        const childToDelete = deletions[i];        if (__DEV__) {          // DEV 环境的货色能够临时不论        } else {          try {            commitDeletion(root, childToDelete, fiber);          } catch (error) {            captureCommitPhaseError(childToDelete, fiber, error);          }        }      }    }    const child = fiber.child;    if ((fiber.subtreeFlags & MutationMask) !== NoFlags && child !== null) {      ensureCorrectReturnPointer(child, fiber);      nextEffect = child;    } else {      commitMutationEffects_complete(root);    }  }}

commitMutationEffects_complete

  • 解决传进来的Fibre节点,其nextEffect有值示意须要对该Fiber进行操作,传入commitMutationEffectsOnFiber解决
  • 如果nextEffect没有值,对其Fibre节点进行遍历和调度,ensureCorrectReturnPointer
function commitMutationEffects_complete(root: FiberRoot) {  while (nextEffect !== null) {    const fiber = nextEffect;    if (__DEV__) {      // DEV 环境的货色能够临时不论    } else {      try {        commitMutationEffectsOnFiber(fiber, root);      } catch (error) {        captureCommitPhaseError(fiber, fiber.return, error);      }    }    const sibling = fiber.sibling;    if (sibling !== null) {      ensureCorrectReturnPointer(sibling, fiber.return);      nextEffect = sibling;      return;    }    nextEffect = fiber.return;  }}

commitMutationEffectsOnFiber

  • 对须要操作的Fibre节点进行操作,有ref相干操作的就执行ref相干操作,再依据不同的flags值做不同的DOM操作
  • commitPlacement: 示意解决DOM的插入
  • commitWork:示意对DOM的属性更新
function commitMutationEffectsOnFiber(finishedWork: Fiber, root: FiberRoot) {  const flags = finishedWork.flags;  // 是否须要重置文本内容  if (flags & ContentReset) {    commitResetTextContent(finishedWork);  } // 解决 ref 相干的操作  if (flags & Ref) {    const current = finishedWork.alternate;    if (current !== null) {      commitDetachRef(current);    }    if (enableScopeAPI) {      // TODO: This is a temporary solution that allowed us to transition away      // from React Flare on www.      if (finishedWork.tag === ScopeComponent) {        commitAttachRef(finishedWork);      }    }  }    // 依据不同的 flags值执行不同的操作  const primaryFlags = flags & (Placement | Update | Hydrating);  outer: switch (primaryFlags) {    case Placement: { // 插入新的DOM           commitPlacement(finishedWork);      finishedWork.flags &= ~Placement;      break;    }    case PlacementAndUpdate: { // 更新DOM属性和插入DOM      // Placement      commitPlacement(finishedWork);      finishedWork.flags &= ~Placement;      // Update      const current = finishedWork.alternate;      commitWork(current, finishedWork);      break;    }    case Hydrating: { // SSR 环境下的插入DOM      finishedWork.flags &= ~Hydrating;      break;    }    case HydratingAndUpdate: { // SSR 环境下的插入DOM和更新DOM      finishedWork.flags &= ~Hydrating;      // Update      const current = finishedWork.alternate;      commitWork(current, finishedWork);      break;    }    case Update: { // 更新DOM属性      const current = finishedWork.alternate;      commitWork(current, finishedWork);      break;    }  }}

commitContainer

  • commitMutationEffects_complete函数的Switch语句的commitWork或commitPlacement办法都会执行到commitContainer
function commitContainer(finishedWork: Fiber) {  if (!supportsPersistence) {    return;  }  switch (finishedWork.tag) {    case ClassComponent:    case HostComponent:    case HostText: {      return;    }    case HostRoot:    case HostPortal: {      const portalOrRoot: {        containerInfo: Container,        pendingChildren: ChildSet,        ...      } = finishedWork.stateNode;      const {containerInfo, pendingChildren} = portalOrRoot;      replaceContainerChildren(containerInfo, pendingChildren);      return;    }  }  invariant(    false,    'This unit of work tag should not have side-effects. This error is ' +      'likely caused by a bug in React. Please file an issue.',  );}