您的位置:首页 > 其它

Virtual Dom原理浅析

2018-10-17 14:26 134 查看

       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>
阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: