虚拟DOM
虚拟 DOM 是和真实 DOM 相对应的,真实 DOM 也就是平时我们所说的 DOM,它是对结构化文本的抽象表达。在 Web 环境中,其实就是对 HTML 文本的一种抽象描述,每一个 HTML 元素对应一个 DOM 节点,HTML 元素的层级关系也会体现在 DOM 节点的层级上,所有的这些 DOM 节点构成一棵 DOM 树。
在传统的前端开发中,通过调用浏览器提供的一组 API 直接对 DOM 执行增删改查的操作。例如,通过 getElementById 查询一个 DOM 节点,通过 insertBefore 在某个节点前插入一个新的节点等。这些操作看似只执行了一条 JavaScript 语法,但它们的执行效率要比执行一条普通 JavaScript 语句慢得多,尤其是对 DOM 进行增删改操作,每一次对 DOM 的修改都会引起浏览器对网页的重新布局和重新渲染,而这个过程是很耗时的。这也是为什么前端性能优化中有一条原则:尽量减少 DOM 操作。
既然操作 DOM 效率低下,那么有什么办法可以解决这个问题呢?在软件开发中,有这么一句话:软件开发中遇到的所有问题都可以通过增加一层抽象而得以解决。DOM 效率低下的这个问题同样可以通过增加一层抽象解决。虚拟 DOM 就是这层抽象,建立在真实 DOM 之上,对真实 DOM 的抽象。这里需要注意,虚拟 DOM 并非 React 所独有的,它是一个独立的技术,只不过 React 使用了这项技术来提高自身性能。
虚拟 DOM 使用普通的 JavaScript 对象来描述 DOM 元素,对象的结构和 2.1 节中 React.createElement 方法使用的参数的结构类似,实际上,React 元素本身就是一个虚拟 DOM 节点。例如,下面是一个 DOM 结构:
<div className="foo">
<h1>Hello React</h1>
</div>
可以用这样的一个 JavaScript 对象来表述:
{
type: 'div',
props: {
className: 'foo',
children: {
type: 'h1',
props: {
children: 'Hello React'
}
}
}
}
有了虚拟 DOM 这一层,当我们需要操作 DOM 时,就可以操作虚拟 DOM,而不操作真实 DOM,虚拟 DOM 是普通的 JavaScript 对象,访问 JavaScript 对象当然比访问真实 DOM 要快得多。到这里,大家可以发现,虚拟 DOM 并不是什么神奇的东西,它只是用来描述真实 DOM 的 JavaScript 对象而已。