React源码系列之初次渲染

(本文说起代码详见ReactElement.js,这里就不为了好看而贴图了)node

首先须要申明在React常常会提到的一些类型:ReactCompositeComponent是自定义组件(复合组件),ReactDOMComponent指的是浏览器自带标签,ReactDOMTextComponent是针对文本节点的。三者面向的类型不一样,但它们的挂载方法都叫作mountComponent(React作了不少的抽象封装,使各个函数功能可以处理各类结点等而不须要到处修改)。此外,咱们一般所说的Virtual DOM 是ReactElement,并经过ReactDOM的render方法渲染到真实DOM上。面试

那么为了实现渲染,究竟须要那些核心功能呢?浏览器

首先必定须要一个component类,用来表示组件在渲染、更新、删除时应该作些什么事情;而后须要一个component工厂方法,用来返回一个component实例(这样就可使返回实例能够屏蔽底层对具体类型的判断和处理);另外须要mountComponent方法,用来在component渲染时生成DOM结构;最后还须要render方法做为渲染的入口方法,内部经过事务来触发挂载,将内容写入对应的container中去。app

那么具体来讲,初次渲染是怎么一个流程呢?又是怎么利用这些核心功能的呢?函数

咱们知道React的虚拟DOM的概念,事实上,React.createElement就会建立一个这样的虚拟DOM。在React.createElement方法中,会首先检测config参数,而它包含着咱们在使用React组件时可能会传入的ref、key(优化效率)、onClick等,此时ReactElement会将其保存为内部属性留与后用,而后,将其中的属性传入props保存,而且子元素children也会被保存到props。以后会调用ReactElement来返回虚拟DOM,而ReactElement貌似是个构造函数,实际上就是个工厂函数了,而且经过 $$typeof: REACT_ELEMENT_TYPE 来将其标记为ReactElement。固然,若是打debugger调试的话,也会并不意外的发现这些方法会recursive的调用,下面将要提到的instantiateReactComponent 也是同样,没办法,DOM树就这样嘛。(本段说起代码详见ReactElement.js)优化

由于有了ReactElement,就须要将其渲染出来,也就来到了instantiateReactComponent方法。这个方法本质上也是工厂函数,而且在内部会对须要render的node类型进行判断,调用不一样的方法来区别渲染。这样对于render而言,就不须要关心具体类型了。固然一个有意思的点是,ReactCompositeComponentWrapper做为ReactCompositeComponent的Wrapper,实际上就是assign了instantiateReactComponent方法,也就是说,对于不一样的node,各自调用instantiateReactComponent就能够渲染各自的component实例了。固然啦,像我此时试验所用的<App />根组件就是返回的ReactCompositeComponentWrapper实例。spa

这里继续看ReactCompositeComponent。不妨看看performInitialMount方法,它会在内部会调用componentWillMount钩子和_processPendingState,而后先将子ReactElement用_instantiateReactComponent渲染成child(ReactCompositeComponentWrapper),接着再将其用ReactReconciler.mountComponent渲染成一个Markup。事实上,这个调和器也是相似前面的工厂函数同样,屏蔽了想要mount的component的类型,在内部仍旧统一调用了mountComponent,换句话说,Markup就是child.mountComponent。而Markup就是ReactDOMComponent,若是将其打印的话能够看到,它就是那个准备被insertBefore到真实DOM树的,哈哈。主要流程以下(其实仍是蛮简化的,不过应该算是很重要的部分了吧)。debug

初次渲染主流程

在一篇文章上看到这样的图,相较而言更体现出instantiateReactComponent对不一样元素类型的屏蔽,可是我画的完整一点吧。可留做参考。调试

参考的文章里的图

最后,既然上面已经出现了componentWillMount,可知,在咱们终于要完成初次渲染的旅程时,必定会有componentDidMount,至于具体在哪,就不具体指出了。总之,如今想一想过去面试常被问的生命周期,真不是什么上档次的问题…component

后续会对更完整的更新机制进一步作探究。

相关文章
相关标签/搜索