Virtual Dom原理浅析
React开发人员敦促你在编写组件时使用一种称为JSX的语法,混合了HTML和JavaScript。但浏览器对JSX及其语法毫无头绪,浏览器只能理解纯碎的JavaScript,所以JSX必须转换成JavaScript。这里是一个div的JSX代码,它有一个class name和一些内容:
[code]<div className='cn'> Content! </div>
以上的代码,被转换成“正经”的JavaScript代码,其实是一个带有一些参数的函数调用:
[code]React.createElement( 'div', { className: 'cn' }, 'Content!' );
让我们仔细看看这些参数。
- 第一个是元素的type。对于HTML标签,它将是一个带有标签名称的字符串。
- 第二个参数是一个包含所有元素属性(attributes)的对象。如果没有,它也可以是空的对象。
- 剩下的参数都可以认为是元素的子元素(children)。元素中的文本也算作一个child,是个字符串’Content!’ 作为函数调用的第三个参数放置。
你应该可以想象,当我们有更多的children时会发生什么:
[code]<div className='cn'> Content 1! <br /> Content 2! </div>
[code]React.createElement( 'div', { className: 'cn' }, 'Content 1!', // 1st child React.createElement('br'), // 2nd child 'Content 2!' // 3rd child )
把组件(components)组合成页面(page)
所以,我们已经将所有JSX组件转换为纯JavaScript,现在我们有一大堆函数调用,它的参数会被其他函数调用的,或者还有更多的其他函数调用这些参数…这些带参数的函数调用,是怎么转化成组成这个页面的实体DOM的呢?为此,我们有一个ReactDOM库及其它的render方法:
[code]function Table({ rows }) { /* ... */ } // defining a component // rendering a component ReactDOM.render( React.createElement(Table, { rows: rows }), // "creating" a component document.getElementById('#root') // inserting it on a page );
当ReactDOM.render被调用时,React.createElement最终也会被调用,返回以下对象:
[code]// There are more fields, but these are most important to us { type: Table, props: { rows: rows }, // ... }
这些对象,在React的角度上,构成了虚拟DOM。
他们将在所有进一步的渲染中相互比较,并最终转化为 真正的DOM(virtual VS real, 虚拟DOM VS 真实DOM)。
下面是另一个例子:这次div有一个class属性和几个children:
[code]React.createElement( 'div', { className: 'cn' }, 'Content 1!', 'Content 2!', );
变成:
[code]{ type: 'div', props: { className: 'cn', children: [ 'Content 1!', 'Content 2!' ] } }
需要注意的是,那些除了type和attribute以外的属性,原本是单独传进来的,转换之后,会作为在props.children以一个数组的形式打包存在。也就是说,无论children是作为数组还是参数列表传递都没关系 —— 在生成的虚拟DOM对象的时候,它们最后都会被打包在一起的。
进一步说,我们可以直接在组件中把children作为一项属性传进去,结果还是一样的:
[code]<div className='cn' children={['Content 1!', 'Content 2!']} />
在构建虚拟DOM对象完成之后,
ReactDOM.render将会按下面的原则,尝试将其转换为浏览器可以识别和展示的DOM节点:
- 如果type包含一个带有String类型的标签名称(tag name)—— 创建一个标签,附带上props下所有attributes。
- 如果type是一个函数(function)或者类(class),调用它,并对结果递归地重复这个过程。
- 如果props下有children属性 —— 在父节点下,针对每个child重复以上过程。
最后,得到以下HTML(对于我们的表格示例):
[code] <table> <tr> <td>Title</td> </tr> ... </table>阅读更多
- virtual-dom原理与简单实现
- Vue实现virtual-dom的原理简析
- Delegate 原理浅析
- XML的四种解析器(dom,sax,jdom,dom4j)原理及性能比较
- 浅析集群及LVS原理
- 【浅析】ActiveMQ传输文件的几种方式原理与优劣
- Java动态代理实现原理浅析
- GWT RPC 原理浅析二
- SQL injection(SQL 注入攻击) 原理浅析
- java虚拟机原理浅析
- VirtualAPK插件化方案原理探索
- Dubbo解析及原理浅析
- CLR 中类型字段的运行时内存布局 (Layout) 原理浅析 [1]
- 浅析c++函数重载的原理
- C++STL技术原理浅析与应用基础之vector
- 浅析Python运行原理
- DOM中事件处理概览与原理的全面解析
- Vue.js 2.0 - Virtual DOM到底是什么样的
- 【thrift】 thrift原理浅析
- js操作DOM的原理