React 源码(四)React 模式

2021-03-02  本文已影响0人  bowen_wu

概述

官方文档中有三种模式

为啥会有三种模式,React 官方文档也给出了相关说明,咱们从源码的上看看三者有何区别

ReactDOM.createBlockingRoot VS ReactDOM.createRoot

ReactDOM.createBlockingRoot

export function createBlockingRoot(container: Container, options?: RootOptions): RootType {
  return new ReactDOMBlockingRoot(container, BlockingRoot, options);
}

function ReactDOMBlockingRoot(container: Container, tag: RootTag, options: void | RootOptions) {
  this._internalRoot = createRootImpl(container, tag, options);
}

ReactDOM.createRoot

export function createRoot(container: Container, options?: RootOptions): RootType {
  return new ReactDOMRoot(container, options);
}

function ReactDOMRoot(container: Container, options: void | RootOptions) {
  this._internalRoot = createRootImpl(container, ConcurrentRoot, options);
}

可以从代码中看出,二者都返回一个对象,这个对象中有一个 _internalRoot 属性,属性值为 createRootImpl 的返回值,并且传入 createRootImpl 的第二个参数是不同的,一个是 BlockingRoot 一个是 ConcurrentRoot。在源码中还可以看见 render 方法

ReactDOMRoot.prototype.render = ReactDOMBlockingRoot.prototype.render = function (children: ReactNodeList): void {
  const root = this._internalRoot;
  updateContainer(children, root, null, null);
};

也就是说两者最终都调用了 updateContainer 方法

ReactDOM.render

export function render(element: React$Element<any>, container: Container, callback: ?Function) {
  return legacyRenderSubtreeIntoContainer(null, element, container, false, callback);
}

function legacyRenderSubtreeIntoContainer(
  parentComponent: ?React$Component<any, any>,
  children: ReactNodeList, 
  container: Container, 
  forceHydrate: boolean, 
  callback: ?Function
) {
  let root: RootType = (container._reactRootContainer: any);
  let fiberRoot;

  if (!root) {
    // Initial mount
    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);
    });
  } else {
    fiberRoot = root._internalRoot;
    if (typeof callback === 'function') {
      const originalCallback = callback;
      callback = function () {
        const instance = getPublicRootInstance(fiberRoot);
        originalCallback.call(instance);
      };
    }
    // Update
    updateContainer(children, fiberRoot, parentComponent, callback);
  }

  return getPublicRootInstance(fiberRoot);
}

// legacyCreateRootFromDOMContainer
function legacyCreateRootFromDOMContainer(container: Container, forceHydrate: boolean): RootType {
  const shouldHydrate = forceHydrate || shouldHydrateDueToLegacyHeuristic(container);
  // First clear any existing content.
  if (!shouldHydrate) {
    let rootSibling;
    while ((rootSibling = container.lastChild)) {
      container.removeChild(rootSibling);
    }
  }
  return createLegacyRoot(container, shouldHydrate ? {hydrate: true} : undefined);
}

// createLegacyRoot
export function createLegacyRoot(container: Container, options?: RootOptions): RootType {
  return new ReactDOMBlockingRoot(container, LegacyRoot, options);
}

从代码中可以看到,render -> legacyRenderSubtreeIntoContainer -> legacyCreateRootFromDOMContainer -> createLegacyRoot -> ReactDOMBlockingRoot,即 renderrootReactDOMBlockingRoot 的实例,但是这里的参数是 LegacyRoot。并且在 legacyRenderSubtreeIntoContainer 函数中也调用了 updateContainer

三种模式特性对比

上一篇下一篇

猜你喜欢

热点阅读