虚拟DOM和DOM diff

444 阅读2分钟

虚拟DOM

一个可以代表DOM树的对象,通常含有标签名,标签属性,事件监听、子元素和一些其他属性。

在一些情况下,虚拟DOM确实比DOM快,但不代表DOM操作一定比虚拟DOM慢。


虚拟DOM的优点

减少DOM操作的次数

  • 虚拟DOM可以将多次操作合并为一次,比如向页面中添加1000个节点,虚拟DOM不需要做一个接一个的拼接操作,而是将这1000个节点放在数组,然后将这些节点一次性放入页面中,这样只需要一次操作就可以将1000个节点放入页面中了。

  • 虚拟DOM借助DOM diff可以省掉多余的操作,DOM diff通过对比节点的新旧,只取出新增的节点更新,减少DOM操作的范围。

跨平台

虚拟DOM不仅可以变成DOM,还可以变成诸如小程序、IOS应用、安卓应用、因为虚拟DOM本质上来讲是一个JS对象。


虚拟DOM的缺点

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


DOM diff

DOM diff是什么?

  • DOM diff就是一个函数,可以称之为patch。
  • changed = patch(oldVNode,newVNode)
  • changed就是要运行的DOM操作。

changed可能长这样:

[
{type: 'INSERT', vNode: ... },
{type: 'TEXT', vNode: ... },
{type: 'PROPS', propsPatch: [ ... ] }
]

DOM diff的大概逻辑:

Tree diff

  • 将新旧两棵树逐层对比,找到哪些节点需要更新。
  • 如果节点是组件就看Component diff。
  • 如果节点是标签就看 Element diff。

Component diff

  • 如果节点是组件,先看组件的类型。
  • 类型不同会直接替换(即删除旧节点)。
  • 类型相同则只会更新属性。
  • 然后深入组件再做Tree diff(递归)。

Element diff

  • 如果节点是原生标签,则看标签名。
  • 标签名不同直接替换(直接删除旧标签)。
  • 标签名相同则只更新属性。
  • 然后进入标签后代再做Tree diff(递归)。