虚拟DOM是什么

一个能代表DOM树的对象,通常含有标签名,标签上的属性,事件监听和子元素们,以及其他属性/

虚拟DOM的优点

  • 减少DOM操作:虚拟DOM可以将多次操作合并为一次操作,比如你添加1000个节点,却是一个接一个操作的(减少频率)。虚拟DOM借助DOM diff可以把多余的操作省掉,比如你添加1000个节点,其实只有10个是新增的(减少范围)
  • 跨平台:虚拟DOM不仅可以变成DOM,还可以变成小程序,iOS医用,安卓应用,因为虚拟DOM本质上是一个JS对象

    虚拟DOM的缺点

    需要额外的创建函数,如createElement或h,但可以通过JSX来简化成XML写法。

    DOM diff是什么

    是虚拟 DOM 的一种对比算法,当数据发生变化时,它会去对比前后的 DOM ,查找哪些地方发生了变化,然后返回需要改变的操作,其实是一个函数,我们称之为patch,patches = patch(oldVNode,newVNode),patches就是要运行的DOM操作,可能长这样:
    1. [
    2. {type: 'INSERT', vNode: ... },
    3. {type: 'TEXT', vNode: ... },
    4. {type: 'PROPS', propsPatch: [...]}
    5. ]
    其中可能的大概逻辑是:
    1.首先是做 Tree diff,将新旧两棵树逐层对比,找出哪些节点需要更新,如果节点是组件就看 Component diff,如果节点是标签就看 Element diff。
    2.在Component diff中,如果节点是组件,就先看组件类型,类型不同直接替换(删除旧的),类型相同则只更新属性,然后深入组件做 Tree diff(递归)。
    3.在Element diff中,如果节点是原生标签,则看标签名,标签名不同直接替换,相同则只更新属性,然后进入标签后代做 Tree diff(递归)。

    DOM diff的优点和问题

    从上面的描述中可知,通过使用 DOM diff,我们可以只更新发生了改变的节点,而不必每次更新所有的节点,但是 DOM diff 也是存在一定问题的,那就是在同级节点中对比会有一些 bug,会出现识别错误的问题,因为计算机总是会从左到右、从上到下进行计算,假设现在有三个同级节点,当我们删除了第二个节点后,在 DOM diff 算法中,其实并不是认为删除了第二个节点,而是认为原本的第二个节点发生了改变,变成了第三个节点的内容,而第三个节点则被认为是删除了,那么怎么避免这个问题呢?这就需要给每一个节点加上一个唯一的属性 key,来标识每个节点,这要就可以避免识别错误,也就是为什么在 vue 中的 v-for 里必须要声明 :key。