Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
qppq54s opened this issue Jul 6, 2020 · 0 comments

Comments

@qppq54s
Copy link
Owner

qppq54s commented Jul 6, 2020

先断点调试找下调用链条

  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;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant