虚拟 DOM 和 DOM diff

231 阅读2分钟

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]的原理:首先对比11,发现[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。