简况
instantiateReactComponent是在ReactReconciler中被经常引用的一个函数,用于调度并返回组件实例。
目标路径:src/renderers/shared/stack/reconciler/instantiateReactComponent.js
关于这个函数有使用注释,移除DEV和一些警告抛错类函数调用,它大致是这样的:
1 | /** |
它返回的实例有以下几种:
- ReactEmptyComponent.create -> ReactDOMEmptyComponent实例
- ReactHostComponent.createInternalComponent -> ReactDOMComponent实例
- new element.type(element)
- new ReactCompositeComponentWrapper(element) -> ReactCompositeComponentWrapper实例
这几个实例都有一个共性。那就是他们全都在原型上定义了mountComponent、receiveComponent、getHostNode、unmountComponent四个方法。这也是ReactReconciler模块的规划需要。
这里有个补充,后来我在<<深入react技术栈>>看到一个小结,说是高屋建瓴也没错,这里可以作为补充:
参数和返回
前面提到的实例类型的返回取决于它的参数,这里一共有四种情况。
type | 末节点调用 |
---|---|
null 或 false | ReactEmptyComponent.create |
string | ReactDOMComponent |
function && element.type原生组件 | element.type(element) |
function && element.type自定义组件 | new ReactCompositeComponentWrapper(element) |
ReactEmptyComponent
当node传入值为null 或者 false时候回返回它。
1 | var ReactDOMEmptyComponent = function(instantiate) { |
那么可以设想一下?什么情况下,node值会是null 或者 false?
回顾一下之前提到的jsx到js的转换,我们都jsx在转换后,children会依次按层级放在其父元素的type属性上。那么可想而知我们最终节点是没有children的,此时node值可能会是null 或者 false。
但是,虽然上文的推论很浅显直观,但是它是有漏洞的。不仅仅是自定义组件内部会含有html标记,而且一般来说末节点才有可能是null或者false,但是一般来说它都是string,也就是说末节点一般是常规的html标记。
准确的来讲,以下情况才是会发生返回这种children的场景:
1 | class Foo extends React.Component{ |
ReactCompositeComponent line511-514,对child的取值。当达到末节点,此时type为null。
1 | var child = this._instantiateReactComponent( |
而且这个实例中有一个属性 this._currentElement = null
会被其用到。
ReactDOMComponent
ReactDOMComponent的情况可能是最容易理解的,当渲染的元素是HTML标准的div
、span
标记这类, 此时type类型就是string。
这种情况情况常常发生在末节点,和自定义组件里面的children里。
element.type(element)
暂时可用于一些非字符串标识的自定义组件,不过目前来说这是一个当前版本的妥协(临时措施), 未来版本会将其作为字符串标识,完成之后这个分支会被删除。
ReactCompositeComponentWrapper
ReactCompositeComponentWrapper比较常规。它用来处理自定义组件,比如之前提到的Foo
组件就需要用它来处理一遍。
这个函数的作用呢就是对自定义组件做一些处理,比如我们的生命周期函数,事件绑定等一般都是在这里,当组件挂载、更新、卸载也都需要一个比较专门的逻辑来处理。不过虽然如此,但是这个函数其实也是相对抽象的,因为一旦到了type为string时候它会将事情转交给ReactDOMComponent模块。
它本身更多的是对自定义组件的生命周期调用、事务处理、状态更新进行了抽象。