1. 虚拟 DOM 是什么
虚拟 DOM 就是一个能代表 DOM 树的对象,通常含有标签名、标签上的属性、事件监听和子元素们以及其它属性
2. 虚拟 DOM 的优点
- 减少不必要的 DOM 操作:
虚拟 DOM 可以将多次操作合并为一次操作,减少 DOM 操作的次数。比如要添加1000个节点,并非一个接一个操作。
虚拟 DOM 借助 DOM diff 可以把多余的操作省掉,减少DOM操作的范围。比如要添加1000个节点,其实只有10个是新增的
- 跨平台渲染: 虚拟 DOM 不仅可以变成 DOM ,还可以变成小程序、iOS 应用、安卓应用,因为虚拟 DOM 本质上只是一个 JS 对象
3. 虚拟 DOM 的缺点
需要额外的创建函数,如 create Element 或 h,但是可以通过 JSX 来简化成 XML 写法
4. DOM diff 是什么
DOM diff 是一个函数,我们称之为patch。
patches = patch(oldVNode,newVNode) 就是要运行的 DOM 操作。比对 (diff) 渲染更新前后产生的两个虚拟 DOM对象的差异,并产出差异补丁对象,再将差异补丁对象应用到真实 DOM 节点上。
5. DOM diff 的优点
可以把多余的操作省掉,减少 DOM 操作的范围
6. DOM diff 的问题
同级节点对比存在误删的 bug
举个栗子:(源自@方应航)
假设有三个子组件,每个子组件里面有一个「有状态的」孙子组件。
没有使用key的时候,你想把第二个方块删除掉,你想要到的结果是剩下三角和圆圈,但是真实的结果却是剩下三角和方框
这是因为,Vue 做了两件事:先把2变成3,再把3删除掉
计算机对比数组[1,2,3] 和 [1,3]的原理:首先对比1和1,发现[1没变」;然后对比2和3,发现「2变成了3」;最后对比undefined和3,发现[3被删除了」。所以计算机的结论是:「2变成了 3」以及「3被删除了」
解决方法:给每一个元素一个 id,用 id 做 key 值
注意:不能用 index 作为 key
如果你用 index 作为 key,那么在删除第二项的时候,index 就会从1 23变成1 2(因为 index 永远都是连续的,所以不可能是1 3),那么 Vue 依然会认为你删除的是第三项。也就是会遇到上面一样的 bug。