1. 虚拟 DOM 是什么
一个能代表 DOM 树的对象,通常含有标签名、标签上的属性、事件监听和子元素们,以及其他属性
2. 虚拟 DOM 的优点
2.1.减少不必要的 DOM 操作
- 虚拟 DOM 可以将多次操作合并为一次操作(减少频率)
- 比如你添加 1000 个节点,却是一个接一个操作的
虚拟 DOM 借助 DOM diff 可以把多余的操作省掉(减少范围)
虚拟 DOM 不仅可以变成 DOM,还可以变成小程序、iOS 应用、安卓应用,因为虚拟 DOM 本质上只是一个 JS 对象
3. 虚拟 DOM 的缺点
需要额外的创建函数,如
createElement或h,但可以通过 JSX 来简化成 XML 写法
关于创建虚拟 DOM 和简化可见另一篇博客4. DOM diff 是什么
定义:就是虚拟 DOM 的对比算法
- DOM diff 就是一个函数,我们称之为
patch -
patches = patch(oldVNode, newVNode)(括号里分别表示新旧两个虚拟的 DOM 节点) -
patches就是要运行的 DOM 操作,可能长这样:[{type: 'INSERT', vNode: ... },{type: 'TEXT', vNode: ... },{type: 'PROPS', propsPatch: [...]}]
DOM diff 可能的大概逻辑
1.Tree diff
将新旧两棵树逐层对比,找出哪些节点需要更新
- 如果节点是组件就看 Component diff
-
2.Component diff
如果节点是组件,就先看组件类型
类型不同直接替换(删除旧的)
- 类型相同则只更新属性
-
3.Element diff
如果节点是原生标签,则看标签名
标签名不同直接替换,相同则只更新属性
- 然后进入标签后代做 Tree diff(递归)
示例:将虚拟 DOM 想象成树形
<div :class="x"><span v-if="y">{string1}</span><span>{string2}</span></div>
当数据变化时
- 比如:x 从 red 变成 green
- 原本:
现在: 
- DOM diff 发现
- div 标签类型没变,只需要更新 div 对应的 DOM 的属性
- 子元素没变,不更新
- 原本:
- 再比如:y 从 true 变成 false
- 原本:
现在: 
- DOM diff 发现
- div 没变,不用更新
- 子元素1标签没变,但是children变了,更新 DOM 内容
- 子元素2不见了,删除对应的 DOM
- 原本:
补充:如果这个元素有 key,那么就会去找到对应的key,看有没有改变
5. DOM diff 的优点
6. DOM diff 的缺点
同级节点对比存在 bug
比如上面的那个例子:
[x] 明明是删除的第一个节点
hello- 但是实际却是将第一个节点的
hello变成了world解决办法:就是给其加上唯一的
key,这也就是为什么使用 v-for 的时候必须加上 :key 的原因
