为什么 Vue.js 使用 VDOM?

Why is Vue.js using a VDOM?

According to Vue.js' documentation,它在底层使用 VDOM 渲染 UI。以我的理解,VDOM主要是为了避免"tracked dependencies"而发明的。使用 VDOM,可以在不知道到底发生了什么变化的情况下协调应用程序的更大部分。因此,可以使用普通对象和数组来描述视图,只需要通知框架有关更改(如 React 中的 setState)。然后,比较 VDOM 树,并将所需更改的最小集合应用到真实的 DOM.

另一方面,

Vue.js 使用跟踪依赖项。它确切地知道发生了什么变化,因此可以使用 DOM 绑定。此外,由于大多数 Vue.js 用户已经在使用模板语言,它并没有真正受益于 VDOM 提供的更大的灵活性。那么为什么 Evan 决定使用 VDOM?

这个设计决定有几个方面。

  1. 可维护性和灵活性。直接 DOM 绑定(如在 Vue 1.x 中)对于单个绑定确实是高效和直接的,但当涉及列表时就不那么高效了。当涉及组合时,它会变得更加复杂(例如插槽机制)。对于每一种这样的特性(涉及片段的组合),都需要编写专用的有状态代码,它们可能会相互影响,使系统更难维护。使用 VDOM 将最终的 DOM 操作与特征层完全分开 - 特征代码现在通过声明式组合 VNode 来工作,从而更容易维护和添加新特征。

    此外,VDOM 的这种灵活性也可以让用户绕过模板,直接编写渲染函数。

  2. VDOM 差异不是免费的——事实上,当您 setState() 在大型组件树的根部时,它可能会非常昂贵。这就是为什么在 React 中你需要使用 PureComponent 或实现 shouldComponentUpdate 来绕过部分组件树。使用 dep 跟踪系统,我们可以自动更准确地检测需要更新的组件,因此即使 VDOM 也可以从拥有 dep 跟踪系统中受益。

  3. 依赖跟踪也有其成本 - 对于每个绑定,它需要为跟踪的依赖分配内存。超细粒度的绑定意味着应用程序中将有成千上万的反应式观察者,从而导致额外的内存使用。跟踪系统的粒度应该取决于我们正在构建的应用程序类型。基于对典型应用程序结构的观察,Vue 2 通过跟踪每个组件的依赖关系,使用了一种有点“中粒度”的策略,从而使每个组件成为反应式更新边界。

所以 - 将两者结合起来我们可以从两方面获益:)