ReactDOM.render在react源码中执行之后发生了什么?

ReactDOM.render

通常是如下图使用,在提供的 container 里渲染一个 React 元素,并返回对该组件的引用(或者针对无状态组件返回 null)。本文主要是将ReactDOM.render的执行流程在后续文章中会对创建更新的细节进行分析,文中的源代码部分为了方便阅读将__DEV__部分的代码移除掉了。

ReactDOM.render(
  <App />,
  document.getElementById('root')
);

render

位于:react-dom/src/client/ReactDOMLegacy.js

export function render(
  element: React$Element<any>,  container: Container,  callback: ?Function,
) {
   
  // 验证container是否为有效的DOM节点
  invariant(
    isValidContainer(container),
    'Target container is not a DOM element.',
  );
  return legacyRenderSubtreeIntoContainer(
    null,
    element,
    container,
    false,
    callback,
  );
}

返回了一个legacyRenderSubtreeIntoContainer函数,这里注意有5个参数

parentComponent: 父组件因为是初次创建所以为null。

children: 传入的ReactElement

container: 渲染React的DOM容器

forceHydrate: 判断是否需要协调,在服务端渲染的情况下已渲染的DOM结构是类似的因此可以在对比后进行复用。在服务端渲染的情况下使用ReactDOM.hydrate()与 render() 相同只是forceHydrate会标记为true。

callback: 渲染完成后的回调函数

legacyRenderSubtreeIntoContainer

位于:react-dom/src/client/ReactDOMLegacy.js
作用:

  • 判断是否为初次渲染,如果是就创建root并将root._internalRoot赋值给fiberRoot同时封装callback回调,然后调用unbatchedUpdates立即更新子节点。
  • 如果不是第一次渲染则进入正常的updateContainer流程。
  • 最后getPublicRootInstance(fiberRoot)返回公开的 Root 实例对象。
function legacyRenderSubtreeIntoContainer(
  parentComponent: ?React$Component<any, any>,
  children: ReactNodeList,
  container: Container,
  forceHydrate: boolean,
  callback: ?Function,
) {
   

  // TODO: Without `any` type, Flow says "Property cannot be accessed on any
  // member of intersection type." Whyyyyyy.
  let root: RootType = (container._reactRootContainer: any);
  let fiberRoot;
  if (!root) {
   
    // Initial mount 初次渲染创建FiberRoot
    root = container._reactRootContainer = legacyCreateRootFromDOMContainer(
      container,
      forceHydrate,
    );
    fiberRoot = root._internalRoot;
    if (typeof callback === 'function') {
   
      const originalCallback = callback;
      callback = function() {
   
        const instance = getPublicRootInstance(fiberRoot);
        originalCallback.call(instance);
      };
    }
    // Initial mount should not be batched.
    unbatchedUpdates(() => {
   
      updateContainer(children, fiberRoot, parentComponent, callback
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值