起始篇:Element转化为挂载实例

1,069 阅读3分钟

Element转化为挂载实例主要靠的便是 instantiateReactComponent 方法,这个方法会根据 Element的不同情况来生成不同的挂载实例。这些实例会带有一些方法,来辅助挂载。

背景:

这里多说一些,React会将 一个组件的每一对标签都单独选择合适的方式来处理。比如:

    <div>
        <h1>1234567890</h1>---------(1)
        这些是纯文本----------(2)
        <World/>----------(3)
    </div>

假设以上是一个组件APP。那么其中就包含:

(1)element的类型为Object,element.type 为 'h1' 也就是字符串。

(2)element的类型为 string。

(3)element的类型为Object,且element.type 为 'f world(props)'也就是function。

这些便对应了instantiateReactComponent方法的不同类型。

instantiateReactComponent 方法

instantiateReactComponent方法在 instantiateReactComponent 模块中,关于这个方法的作用,源码中是这么介绍的:

Given a ReactNode, create an instance that will actually be mounted.

很明显,这句话的意思就是 这个方法会接受一个 ReactNode ,然后根据这个ReactNode 创建一个实例,这个实例是真实要挂载的实例。

看一个例子

_renderNewRootComponent 方法中

在 ReactMount模块中的 _renderNewRootComponent 方法中用到了这个方法。 nextElement 就是一个 ReactNode 。 nextElement 是 使用ReactElement 方法构建的一个 element。而element 则在前边的文章中有叙述。 所以,我们可以很简单的知道 所谓的 ReactNode 就是一个 element。

    var componentInstance = instantiateReactComponent(nextElement, null);

那么我们就来看看instantiateReactComponent是如何处理 element 为一个真正要挂载的 实例。

首先。React组件,浏览器是不认的,最终都是要转换为浏览器你能够识别的HTML标签的,这是前提。

其次,一个React组件你深扒一下他最终还是由HTML标签组成的。

最后,instantiateReactComponent 则是根据不同的情况将ReactNode 生成不同的 实例。

instantiateReactComponent

    function instantiateReactComponent(node) {
      var instance;
    
      if (node === null || node === false) {
        instance = new ReactEmptyComponent(instantiateReactComponent);----------(1)
      } else if (typeof node === 'object') {
        var element = node;
        '
          如果 type的类型是string 则说明它是 普通的HTML标签,那么直接按照普通的方式生成 DOM
          
          而如果不是string的话,比如是
          ƒ ()  ƒ App(props)之类的,则说明他们是 自定义的组件。
          则要另行处理。
        '
        
        if (typeof element.type === 'string') {
            '
            ReactNativeComponent.createInternalComponent 方法是被注入进来的,注入的是 ReactDOMComponent 类。
            最终的结构是 new ReactDOMComponent(element.type,element.props)
    
            生成一个 ReactDOMComponent 的实例返回
            '
            
          instance = ReactNativeComponent.createInternalComponent(element);--------(2)
        } else if (isInternalComponentType(element.type)) {
          instance = new element.type(element);---------------(3)
        } else {
    
            '
            是我们自定义的类的时候 执行该方法来进行生成 instance 操作。
            '
          instance = new ReactCompositeComponentWrapper();----------(4)
          
        }
      } else if (typeof node === 'string' || typeof node === 'number') {
        instance = ReactNativeComponent.createInstanceForText(node);----------(5)
      } else {
        !false ? process.env.NODE_ENV !== 'production' ? invariant(false, 'Encountered invalid React node of type %s', typeof node) : invariant(false) : undefined;
      }
    
     
      instance.construct(node);
    
     
      instance._mountIndex = 0;
      instance._mountImage = null;
    
      return instance;
    }

注意:一般我们开发写的是React组件,而要将React组件变为真实的DOM挂载真实DOM中,就需要将React组件初始化为要挂载的实例。 instantiateReactComponent方法便是负责初始化挂载实例的。

初始化的挂载实例会有其自身的方法,其中一个方法 mountComponent 是核心。而要挂载一个挂载实例其实就是调用一个挂载实例提供的 mountComponent 方法。该方法最终会返回React组件解析的HTML。

最后注意一下就是:React的组件是层层嵌套的,那么React组件实例的挂载也是通过递归来实现。从根组件的挂载,一直到最后一个组件。

接下来我们分开来看看 不同的Element.type 生成的 挂载实例是何种样子。