今天面试问到了这个,之前还真没注意到过这个问题。

DOM

在 web 开发中,DOM 代表文档对象模型,是 HTML 的机构化文本抽象,而 HTML 元素自然也就称为 DOM 中的节点了。

HTML DOM 提供了一系列的 api 来选择或操作j节点。如 getElementById 等。HTML DOM 是 HTML 文档的树形结构的抽象,这简化了我们查询及修改的效率。但是当网页渐变的复杂,DOM 层级不断加深,DOM 节点越来越多。操作起来不免难以管理,而且效率低下,即使使用 jQuery.

VirtualDOM

VirtualDOM 虽然不是 React 创造的概念,却是 React 不同于其他 MVVM 框架的重要原因之一。

VirtualDOM 其实是在 HTML DOM 的基础上进一步抽象出的概念,因为直接操作 DOM 花销太大。React 加入了 VirtualDOM 的概念。

看一下代码片段:

1
2
3
4
ReactDOM.render(
<h1>Hello World!</h1>,
document.getElementById('example')
);

这应该是每个初学者写的第一个 React 示例。这个代码段中,render 方法的第一个参数,即 <h1>Hello World!</h1>;这行代码不是普通的 HTML 代码,而是 jsx。如果不使用 jsx,上面代码等同于,

1
2
3
4
5
6
var hello = React.createElement('h1', null, 'Hello World!');
ReactDOM.render(
hello,
// [hello, hello],
document.getElementById('example')
);

显而易见,render 方法的第一个参数是一个 React 节点,(react16 中也可以是节点数组)。第二个参数则是节点所要挂载的 HTML DOM。事实上,jsx 代码段也只是简化开发而为之,其最后还是被解释为一个个 ReactElement 。

React.createElement 可以是 HTML 原生标签,也可以是多个标签的组合。VirtaulDOM 也就是由 React Element 构建的树形结构.

但是,目前为止这些 React Element 都是无状态的(stateless)。可以使用 React.createClass 创建状态组件,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var People = React.createClass({
getInitialState: function() {
return { name: this.props.name || 'Bao' };
},
render: function() {
return (
<p>I am {this.state.name}. </p>
);
}
});
var me = React.createElement(People, { name: 'BaoXuebin' });
ReactDOM.render(
me,
document.getElementById('example')
);

值得注意的是,React16 已经删除了 createClass 方法,推荐使用 ES6 继承 React.Component

显然,VirtualDOM 是 ReactElement 的树形集合,它比 HTML DOM 简洁的多。之后的 Diff 算法去比较前后 VirtualDOM 的结构差异,然后精准的代替我们手动的操作 DOM。由此可见,VirtualDOM 更像是一个工具,帮我们自动的分析 HTML DOM 的差异并精确的对其进行操作,现在看来,VirtualDOM 比 DOM 快 这句话就显得很滑稽了。

参考:

https://www.fullstackreact.com/p/jsx-and-the-virtual-dom/
http://reactkungfu.com/2015/10/the-difference-between-virtual-dom-and-dom/