什么是虚拟dom

Vue的虚拟dom也是Javascript的对象,不过Vue创建的虚拟dom要比浏览器中实际的dom小很多。

比如有html

<div>
    <p>123</p>
</div>
对应的虚拟dom(伪代码):
var Vnode = {
    tag: 'div',
    children: [
        { tag: 'p', text: '123' }
    ]
};
这样看来,虚拟dom比真实dom要简单的多。

为什么使用虚拟dom

1. 性能上得到提升,因为真实dom比虚拟dom更为复杂。

2. 解耦html依赖,不再依赖HTML 解析器进行模版解析。

3. 跨平台,虚拟dom依赖js对象而不是浏览器的dom对象。

Diff算法

在Vue中当有组件的创建和更新时,Vue会执行内部的update函数,该函数会生成新的虚拟dom树,将新旧两个dom树进行比较,找到其中有变化,就会更新到真实的dom。其中,比较差异的过程叫做diff算法。

Vue虚拟dom概念

如图所示,Vue diff算法是同层次比较,只会比较同一个层次的节点。

在判断两个节点是否相同时,vue是通过虚拟节点的key和tag来进行判断的。

具体来说,首先对根节点进行对比,如果相同则将旧节点关联的真实dom的引用挂到新节点上,然后根据需要更新属性到真实dom,然后再对比其子节点数组;如果不相同,则按照新节点的信息递归创建所有真实dom,同时挂到对应虚拟节点上,然后移掉旧的dom。

在对比其子节点数组时,vue对每个子节点数组使用了两个指针,分别指向头尾,然后不断向中间靠拢来进行对比,这样做的目的是尽量复用真实dom,尽量少的销毁和创建真实dom。如果发现相同,则进入和根节点一样的对比流程,如果发现不同,则移动真实dom到合适的位置。

这样一直递归的遍历下去,直到整棵树完成对比。