You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
这里看下 API: React.createElement(component, props, ...children)。它生成一个 js 的对象,这个对象是用来代表一个真实的 dom node,这个 js 的对象就是我们俗称的虚拟dom。(虚拟 dom 的意思是用 js 对象结构模拟出 html 中 dom 结构,批量的增删改查先直接操作 js 对象,最后更新到真正的 dom 树上。因为直接操作 js 对象的速度要比操作 dom 的那些 api 要快。) 譬如根元素 <div className="test"></div> 生成对应出来的虚拟 dom 是:
有了虚拟 dom,接下来的工作就是把这个虚拟 dom 树真正渲染成一个 dom 树。React 的做法是针对不同的 type 构造相应的渲染对象,渲染对象提供一个 mountComponent 方法(负责把对应的某个虚拟 dom 的节点生成成具体的 dom node),然后循环迭代整个 vdom tree 生成一个完整的 dom node tree,最终插入容器节点。查看源码你会发现如下代码:
// vdom 是第3步生成出来的虚拟 dom 对象varrenderedComponent=instantiateReactComponent(vdom);// dom nodevarmarkup=renderedComponent.mountComponent();// 把生成的 dom node 插入到容器 node 里面,真正在页面上显示出来// 下面是伪代码,React 的 dom 操作封装在 DOMLazyTree 里面containerNode.appendChild(markup);
instantiateReactComponent 传入的是虚拟 dom 节点,这个方法做的就是根据不同的 type 调用如下方法生成渲染对象:
// 如果节点是字符串或者数字returnReactHostComponent.createInstanceForText(vdom(string|number));// 如果节点是宿主内置节点,譬如浏览器的 html 的节点returnReactHostComponent.createInternalComponent(vdom);// 如果是 React component 节点returnnewReactCompositeComponentWrapper(vdom);
ReactHostComponent.createXXX 也只是一层抽象,不是最终的的渲染对象,这层抽象屏蔽了宿主。譬如手机端(React native)和浏览器中同样调用 ReactHostComponent.createInternalComponent( vdom ); 他生成的最终的渲染对象是不同的,我们当前只讨论浏览器环境。字符串和数字没有什么悬念,在这里我们就不深入探讨了,再进一步看,div 等 html 的原生 dom 节点对应的渲染对象是 ReactDOMComponent 的实例。如何把 { type:'div', ... } 生成一个 dom node 就在这个类(的 mountComponent 方法)里面。(对如何生成 div、span、input、select 等 dom node 感兴趣的可以去探究 ReactDOMComponent,这里不做具体的讨论,本文只是想总结下 React 整个渲染过程。下面只给出一个最简示例代码:)
React 渲染过程
<div className="test">...</div>
)为例,用 babel 把 jsx 转成 js 后得到如下代码:<div className="test"></div>
生成对应出来的虚拟 dom 是:除了一些 dom 相关的属性,虚拟 dom 对象还包括些 React 自身需要的属性,譬如:ref,key。最终示例中的 jsx 生成出来的虚拟 dom,大致如下:
instantiateReactComponent 传入的是虚拟 dom 节点,这个方法做的就是根据不同的 type 调用如下方法生成渲染对象:
ReactHostComponent.createXXX 也只是一层抽象,不是最终的的渲染对象,这层抽象屏蔽了宿主。譬如手机端(React native)和浏览器中同样调用 ReactHostComponent.createInternalComponent( vdom ); 他生成的最终的渲染对象是不同的,我们当前只讨论浏览器环境。字符串和数字没有什么悬念,在这里我们就不深入探讨了,再进一步看,div 等 html 的原生 dom 节点对应的渲染对象是 ReactDOMComponent 的实例。如何把 { type:'div', ... } 生成一个 dom node 就在这个类(的 mountComponent 方法)里面。(对如何生成 div、span、input、select 等 dom node 感兴趣的可以去探究 ReactDOMComponent,这里不做具体的讨论,本文只是想总结下 React 整个渲染过程。下面只给出一个最简示例代码:)
我们再看下 React component 的渲染对象 ReactCompositeComponentWrapper(主要实现在 ReactCompositeComponent 里面,ReactCompositeComponentWrapper 只是一个防止循环引用的 wrapper)
|
babel and
React.createElement
|
v
|
var domNode = new ReactDOMComponent( vdom ).mountComponent();
|
v
|
|
v
containerDomNode.appendChild( domNode );
以上是 React 渲染 dom 的一个基本流程,下一篇计划总结下更新 dom 的流程,即 setState 后发生了什么。
The text was updated successfully, but these errors were encountered: