# Virtual DOM 的优化

VDOM 的价值在于用完全用 JS 描述 UI, 但代价是过大的性能开销. 它开销大的地方在于当触发微小更新时, 仍然要重新生成整个 app 的 Virtual DOM, 然后与旧的 Virtual DOM 进行比对. 虽然 Vue 可以在组件的层级上做最小化更新. 但是组件的粒度是可大可小的. 一旦组件内部也很复杂庞大, 之前的问题还是没有得到根本的解决. 这就是传统 vdom 的缺点.

传统的 vdom 的性能不是根据模板的动态节点的多少决定的, 而是根据模板本身的大小决定的. 于是当一个模板的动态节点并不多且模板体积过大时, 使用传统 vdom 就会造成极大的性能浪费.

传统 vdom 的缺点与它的出身是紧密相关的, vdom 一开始是在 react 里的, 我们用 JSX 来手写 render function, JSX 的语法来自于 JS, 由于 JS 的灵活性使其编写体验还算不错, 但是也使 vdom 的优化工作十分难做. vdom 不得不在每次数据更新时重新生成一个 vdom.

模板编译的最大的好处就是十分方便做 vdom 的优化. 以下面代码为例:

<template>
  <div>
    <p>1</p>
    <p>{{ n }}</p>
    <p>3</p>
  </div>
</template>
1
2
3
4
5
6
7

我们通过模板可以知道只有n是动态数据, 因此每次生成新的 vdom 时可以直接使用旧 vdom 里除n之外的其余 vnode. 因此也做到了性能优化.这就是 Vue 的解决方案. 而 React 采用的是时间分片. 把静态模板编译做到极致的是 Svelte, 它甚至抛弃了 vdom. 因此可以看见: coding 的灵活性与编译优化是矛盾的. 从前的 React 选择了前者, Svelte 选择了后者.

# Vue 为什么不抛弃 vdom

  • 高级场景下需要 render function 的表达力
  • 兼容 2.x
  • 生成的代码更简洁