vue和React都用到了Virtual DOM,出于好奇和对知识的渴望,就上网查了一下,并整理写篇文章增加记忆。
什么是Virtual DOM
本质上来说,Virtual DOM只是一个简单的JS对象,并且最少包含tag、props和children三个属性。不同的框架对这三个属性的命名会有点差别,但表达的意思是一致的。它们分别是标签名(tag)、属性(props)和子元素对象(children),下面看个例子:
{
tag: "div",
props: {},
children: [
"Hello World",
{
tag: "ul",
props: {},
children: [{
tag: "li",
props: {
id: 1,
class: "li-1"
},
children: ["第", 1]
}]
}
]
}
<div>
Hello World
<ul>
<li id="1" class="li-1">
第1
</li>
</ul>
</div>
这两个是一 一对应的,一个dom对象,比如li
,由tag(li)
, props({id: 1, class: "li-1"})
和children(["第", 1])
三个属性来描述。
Virtual DOM特点
Virtual DOM最大的特点是将页面的状态抽象为 JS 对象的形式,配合不同的渲染工具,使跨平台渲染成为可能。如 React 就借助 Virtual DOM 实现了服务端渲染、浏览器渲染和移动端渲染等功能。
此外,在进行页面更新的时候,借助Virtual DOM,DOM 元素的改变可以在内存中进行比较,再结合框架的事务机制将多次比较的结果合并后一次性更新到页面,从而有效地减少页面渲染的次数,提高渲染效率。
最后引用尤雨溪 的一段话来结束本篇文章,
在比较性能的时候,要分清楚初始渲染、小量数据更新、大量数据更新这些不同的场合。Virtual DOM、脏检查 MVVM、数据收集 MVVM 在不同场合各有不同的表现和不同的优化需求。Virtual DOM 为了提升小量数据更新时的性能,也需要针对性的优化,比如 shouldComponentUpdate 或是 immutable data。
- 初始渲染:Virtual DOM > 脏检查 >= 依赖收集
- 小量数据更新:依赖收集 >> Virtual DOM + 优化(shouldComponentUpdate控制渲染 ) > 脏检查(无法优化) > Virtual DOM 无优化
- 大量数据更新:脏检查 + 优化 >= 依赖收集 + 优化 > Virtual DOM(无法/无需优化)>> MVVM 无优化
不要天真地以为 Virtual DOM 就是快,diff 不是免费的,batching 没MVVM 也能做,而且最终 patch 的时候还不是要用原生 API。在我看来 Virtual DOM 真正的价值从来都不是性能,而是它 为函数式的 UI 编程方式打开了大门;可以渲染到 DOM 以外的 backend,比如 ReactNative。