Skip to content

Vue3 为什么比 Vue2 快

响应式系统:按需代理 vs 全量递归

Vue2 初始化时会对 data 中的所有属性递归执行 Object.defineProperty,无论这些属性是否会被实际访问。对于深层嵌套的大对象,这种初始化成本会比较明显。

Vue3 的 Proxy 采用按需代理策略:只有当某个属性被实际访问时,才会继续为它的子属性创建代理。初始化阶段不再需要递归遍历整棵对象树。

虚拟 DOM Diff:只遍历动态节点

Vue2 的 Diff 是整棵虚拟 DOM 树全量对比,即使 90% 的节点是静态的。Vue3 在编译阶段把动态节点单独抽成 Block Tree,Diff 时跳过所有静态子树。

这并不意味着直接操作 DOM 更合适。绕过 Vue 直接修改 DOM,下一次响应式更新时,手动修改的结果可能会被框架重新渲染覆盖。Vue 的 Diff 机制用于保证 DOM 状态和数据状态的一致性,Vue3 的优化是在保持这种一致性的前提下降低更新成本。

Patch Flag:精准到属性维度的更新

Vue3 会为每个动态节点添加补丁标记,精确到“这个节点只有 class 会变化”或“这个节点只有文本会变化”。Diff 时:

  • 标记了 CLASS 的节点,只比对新旧 class,跳过其他属性
  • 标记了 TEXT 的节点,只比对文本内容
  • 什么都没标记的静态节点,直接跳过

相比之下,Vue2 的 Diff 需要全量比对节点的所有属性和子节点。

Diff 算法本身:双端对比 + 最长递增子序列

Vue2 和 Vue3 都采用同层比较策略(不跨层级比较),但 Vue3 在 Diff 数组子节点时加入了**最长递增子序列(LIS)**算法,可以判断哪些节点可以保持原位,哪些节点需要移动。这个优化在大列表更新场景下效果更明显,节点变动越复杂,LIS 能减少的 DOM 移动操作越多。

打包体积也更小

Vue3 使用 ES Module 输出,支持 Tree-shaking。未使用的 API(例如 Transition)可以在打包阶段被剔除。再加上核心逻辑重写后整体实现更紧凑,在相同功能规模下,最终产物体积通常也会更小。