Virtual DOM

Virtual DOM

Virtual DOM 是一个以 JavaScript object 为基础的数据结构,它描述了 actual DOM 的必要信息

为了理解 virtual DOM,我们需要先对 DOM 有一个初步的认识。DOM 全程 Document Object Model,其是对结构化文档的一种描述和接口。DOM 将整个页面映射为一个由层次节点组成的文件,从而提供了操作页面的编程接口。它是基于对象管理组织(OMG)的规约设计的,所以是中立于平台和语言的。

第一版DOM描述文档于1998年发布。在那个时候,如果我们想要一个更新一个DOM,我们就需要调用 original DOM 的 API,进行诸如获取、创建、挂载等工作。这在更新范围较大,要求时间较短时,性能开销是巨大的。此外,相较于找到某些特定的元素并进行更改,我们经常会选择一口气更新一大片DOM。这样做的确很简单,但却导致了很多的性能问题。

为了在频繁更新DOM时更加高效,所以我们引入了 Virtual DOM。上面的 DOM tree 可以写成如下的 JavaScript object

例如,对如下的 HTML 文档:

1
2
3
4
5
6
7
8
<html lang="en">
<head></head>
<body>
<ul class="list">
<li class="list__item">List item</li>
</ul>
</body>
</html>

其 DOM tree 是这样子的:

html
└─head
└─body
│   └─ul class="list"
│           └─ul class="list__item"
│                   └─"List item"

可写成如下的 JavaScript object

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const vdmo = {
tagName: 'html',
children: [
{
tagName: 'head'
},
{
tagName: 'body',
children: {
tagName: 'ul',
data: {
class: 'list'
},
children: {
tagName: 'li',
data: {
class: 'list__item'
},
children: 'List item'
}
}
}
]
}

这东西从逻辑上将,和 original DOM 是一样的,也是以对象为基础的,HTML 的描述。不过因为 Virtual DOM 是完全的 JavaScript object,所以我们可以很高效的修改它,并且仅在必须的时候才将其转换为 actual DOM。

附加

  1. 只有通过 Virtual DOM 才能实现对 DOM 的特定部分修改吗?
    不一定,基于数据响应机制也可以做到。这其中的核心是让实际生成 DOM 的函数接收到具体更改部分的信息即可。

  2. Vue 1.0 已经实现了数据响应机制,那么为什么还需要在 2.0 中引入 Virtual DOM 充当编程语言和 HTML 的中间层?

    • HTML 无法提供 JS 对象那样复用的能力。
    • 实现了对运行平台的解耦,即跨平台。同时这也剥离了 HTML Parser,提高了运行时效率。

[参考]
https://bitsofco.de/understanding-the-virtual-dom/