什么是虚拟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 diff算法是同层次比较,只会比较同一个层次的节点。
在判断两个节点是否相同时,vue是通过虚拟节点的key和tag来进行判断的。
具体来说,首先对根节点进行对比,如果相同则将旧节点关联的真实dom的引用挂到新节点上,然后根据需要更新属性到真实dom,然后再对比其子节点数组;如果不相同,则按照新节点的信息递归创建所有真实dom,同时挂到对应虚拟节点上,然后移掉旧的dom。
在对比其子节点数组时,vue对每个子节点数组使用了两个指针,分别指向头尾,然后不断向中间靠拢来进行对比,这样做的目的是尽量复用真实dom,尽量少的销毁和创建真实dom。如果发现相同,则进入和根节点一样的对比流程,如果发现不同,则移动真实dom到合适的位置。
这样一直递归的遍历下去,直到整棵树完成对比。