Skip to content

ReactDOM render方法原理解析,react是怎么把元素渲染到DOM节点上的 #11

@qppq54s

Description

@qppq54s

先断点调试找下调用链条

  1. render
  2. legacyRenderSubtreeIntoContainer
  3. updateContainer
  4. scheduleWork(scheduleUpdateOnFiber)
  5. performSyncWorkOnRoot
  6. finishSyncRender
  7. commitRoot
  8. runWithPriority
  9. commitRootImpl
  10. invokeGuardedCallback
  11. commitMutationEffects
  12. commitPlacement
  13. insertOrAppendPlacementNodeIntoContainer
  14. appendChildToContainer
  15. appendChildToContainer
  16. parentNode.appendChild(child)

我们按顺序来看下每个方法做了什么事情

function legacyRenderSubtreeIntoContainer(
  parentComponent: ?React$Component<any, any>,
  children: ReactNodeList,
  container: Container,
  forceHydrate: boolean,
  callback: ?Function,
) {
  let root: RootType = (container._reactRootContainer: any);
  let fiberRoot;
  // 这里根据root判断是否初次挂载(initial mount)
  if (!root) {
    // 根据container创建一个firberRoot,并挂到container上,名称为_reactRootContainer
    root = container._reactRootContainer = legacyCreateRootFromDOMContainer(
      container,
      forceHydrate,
    );
    fiberRoot = root._internalRoot;
   
    unbatchedUpdates(() => {
      // 执行到这里
      updateContainer(children, fiberRoot, parentComponent, callback);
    });
  }
  return getPublicRootInstance(fiberRoot);
}

从代码上看,legacyRenderSubtreeIntoContainer方法主要是创建了一个"firberRoot",然后执行updateContainer方法。
legacyRenderSubtreeIntoContainer这个方法最终调用的是一个叫createFiberRoot的方法,我们线看下这个方法

export function createFiberRoot(
  containerInfo: any,
  tag: RootTag,
  hydrate: boolean,
  hydrationCallbacks: null | SuspenseHydrationCallbacks,
): FiberRoot {
  const root: FiberRoot = (new FiberRootNode(containerInfo, tag, hydrate): any);

  const uninitializedFiber = createHostRootFiber(tag);
  root.current = uninitializedFiber;
  uninitializedFiber.stateNode = root;

  initializeUpdateQueue(uninitializedFiber);
  return root;
}
export function updateContainer(
  element: ReactNodeList,
  container: OpaqueRoot,
  parentComponent: ?React$Component<any, any>,
  callback: ?Function,
): ExpirationTime {
  const current = container.current;
  const currentTime = requestCurrentTimeForUpdate();
  const suspenseConfig = requestCurrentSuspenseConfig();
  const expirationTime = computeExpirationForFiber(
    currentTime,
    current,
    suspenseConfig,
  );
  // 取createFiberRoot方法时添加的current,并执行scheduleWork方法
  scheduleWork(current, expirationTime);
  return expirationTime;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions