什么是虚拟DOM?
使用JS对象模拟出DOM树中的元素和元素嵌套的关系,从而实现页面元素的高效更新.
例如
<div id='div1' class='class-div1'>
<div id='div2' class='class-div2'>123123</div>
</div>
对应的js对象就长这样:
var vdom = {
tagName: 'div',
attr: {
id: 'div1',
class: 'class-div1'
},
children: [
{
tagName: 'div',
attr: {
id: 'div2',
class: 'class-div2'
},
children:[
123123
]
}
]
}
这个vdom就是一个虚拟Dom
虚拟Dom相比于真实Dom的优势在哪里?
真实的Dom在进行数据改变的时候会进行下面几步操作:
- 生成一个真实Dom
- 某些操作导致数据变更,生成一个新的Dom树
- 将新的Dom树完全替换之前的旧Dom树
可以想象一下,这三步操作都很消耗内存,并且代价很大
那么虚拟Dom是怎么进行上面的操作呢?
- 根据虚拟Dom生成一个真实Dom
- 修改数据造成Dom的某个节点需要重新渲染,生成这个新的虚拟Dom
- 比较新旧两次的虚拟Dom找出其中的差异
- 对比两颗Dom树之间的差异,获取到有差异的节点
- 把发生改变的内容进行替换,未发生改变的则不进行替换
这样一来,便大大加快了更新页面的速度,消耗的内存比较小,可以说是很便宜的Dom
Dom的DIFF算法
上面说到了虚拟DOM在更新Dom树之前会进行一次新旧Dom的对比,那么是根据什么进行对比的?
那就是用Dom的Diff算法
Diff算法分成三种:
tree diff
component diff
element diff
他们都是用来对比一个Dom树中不同的部分,三者相结合,那就是虚拟Dom的对比过程了
tree diff:将新的Dom树和旧的Dom树逐层进行比较,比较出不同的Dom树的层次,对比结束后,发生改变的元素一定能够被找到
component diff: 在tree diff的时候,新旧Dom树的每一层中比较每一个组件,如果发现了不同的组件,移除旧的组件,增加新的组件
element diff: 在进行component diff的时候, 在组件类型相同的情况下对比两个组件之中的元素,
详细的Diff算法可以看看这篇文章:
https://www.jianshu.com/p/3ba0822018cf