第七章 commit(React18源码解析七)

141 阅读2分钟

第一章 JSX(React18源码解析一)
第二章 实现Virtual DOM(React18源码解析二)
第三章 根节点关联根Fiber(React18源码解析三)
第四章 初始化UpdateQueue、添加update(React18源码解析四)
第五章 实现时间切片函数和拷贝Fiber(React18源码解析五)
第六章 构建FiberTree(React18源码解析六)
第七章 commit(React18源码解析七)
第八章 React中的事件(React18源码解析八)
第九章 useReducer、useState(React18源码解析九)
第十章 React的dom diff(React18源码解析十)
第十一章 React的Effect(React18源码解析十一)
第十二章 React的同步、并发渲染(React18源码解析十二)
第十三章 React高优打断低优、饥饿问题(React18源码解析十三)

commit任务和调用栈

任务:
react在commit阶段根据fiber.flags即副作业标识从下往上的递归出来真实dom,或更新或插入父dom等

调用栈:
commitRoot=>
commitRootImpl=>
//packages/react-reconciler/src/ReactFiberWorkLoop.old.js
commitMutationEffects=>
commitMutationEffectsOnFiber=>
recursivelyTraverseMutationEffects=>commitMutationEffectsOnFiber
commitReconciliationEffects=>commitPlacement
//packages/react-reconciler/src/ReactFiberCommitWork.js

commitMutationEffectsOnFiber函数(有删减,只列举原生节点这一种情况)

function commitMutationEffectsOnFiber(finishedWork,root,lanes){
  const current = finishedWork.alternate;
  const flags = finishedWork.flags;
  switch (finishedWork.tag) {
      case HostComponent: {
      //根据fiber类型走不同分支,
      //recursivelyTraverseMutationEffects会向下递归调用commitMutationEffectsOnFiber,
      //当下面的节点处理完毕后再调用commitReconciliationEffects处理本节点,
      //本质是一个从root开始递归向下,再递归向上处理的过程
      recursivelyTraverseMutationEffects(root, finishedWork, lanes);
      commitReconciliationEffects(finishedWork);
      //处理ref
      if (flags & Ref) {
        if (current !== null) {
          safelyDetachRef(current, current.return);
        }
      }
      if (supportsMutation) {
        //重置文本节点
        if (finishedWork.flags & ContentReset) {
          const instance = finishedWork.stateNode;
          try {
            resetTextContent(instance);
          } catch (error) {
            captureCommitPhaseError(finishedWork, finishedWork.return, error);
          }
        }
        //根据fiber.updateQueue更新原生节点
        if (flags & Update) {
          const instance = finishedWork.stateNode;
          if (instance != null) {
            const newProps = finishedWork.memoizedProps;
            const oldProps =
              current !== null ? current.memoizedProps : newProps;
            const type = finishedWork.type;
            try {
              commitUpdate(instance, type, oldProps, newProps, finishedWork);
            } catch (error) {
              captureCommitPhaseError(finishedWork, finishedWork.return, error);
            }
          }
        }
      }
      return;
    }
  }
}

recursivelyTraverseMutationEffects函数

function recursivelyTraverseMutationEffects(
  root,
  parentFiber,
  lanes,
) {
  if (parentFiber.subtreeFlags & MutationMask) {
    let child = parentFiber.child;
    //有子节点递归向下
    while (child !== null) {
      commitMutationEffectsOnFiber(child, root, lanes);
      child = child.sibling;
    }
  }
}

commitReconciliationEffects函数

function commitReconciliationEffects(finishedWork) {
  const flags = finishedWork.flags;
  //判断本节点是否有Placement副作用,有调commitPlacement把本节点插入到父节点
  if (flags & Placement) {
    commitPlacement(finishedWork);
    finishedWork.flags &= ~Placement;
  }
  if (flags & Hydrating) {
    finishedWork.flags &= ~Hydrating;
  }
}

commitPlacement函数

function commitPlacement(finishedWork) {
  const parentFiber = getHostParentFiber(finishedWork);
  //根据父节点类型找到父节点原生元素,找到本节点前一个节点,在前一个节点后插入或直接在父节点下添加
  switch (parentFiber.tag) {
    case HostSingleton: {
      if (supportsSingletons) {
        const parent = parentFiber.stateNode;
        const before = getHostSibling(finishedWork);
        insertOrAppendPlacementNode(finishedWork, before, parent);
        break;
      }
    }
    case HostComponent: {
      const parent = parentFiber.stateNode;
      if (parentFiber.flags & ContentReset) {
        resetTextContent(parent);
        parentFiber.flags &= ~ContentReset;
      }
      const before = getHostSibling(finishedWork);
      insertOrAppendPlacementNode(finishedWork, before, parent);
      break;
    }
    case HostRoot:
    case HostPortal: {
      const parent = parentFiber.stateNode.containerInfo;
      const before = getHostSibling(finishedWork);
      insertOrAppendPlacementNodeIntoContainer(finishedWork, before, parent);
      break;
    }
  }
}

备注:

本文为清晰展现出本文核心逻辑把粘贴的源码中参数校验、typescript类型、不相关逻辑等已删除