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 生成的 挂载实例是何种样子。