Skip to content

Vue3 整体变化 ✨

要点速览

  • 分类:源码优化、性能优化、语法 API、RFC 流程。
  • 源码:Monorepo 拆包;TypeScript 重构,类型更完善。
  • 性能:响应式由 Proxy;编译期静态提升、PatchFlags、Block Tree、事件缓存、预字符串化;运行期快速 diff。
  • 语法:Composition API 与 <script setup>;组合式函数替代 mixin;createApp 实现应用级隔离。
  • RFC:公开提案、充分讨论动机/设计/兼容性,迭代更稳健。

变化总览

Vue3 相比 Vue2 的变化可以归纳为四大维度:

  1. 源码工程与类型系统(Monorepo + TypeScript)
  2. 运行时与编译器的性能优化(响应式、编译、diff)
  3. 开发者 API 与编码范式(Composition API、应用创建与隔离)
  4. 社区协作流程(RFC 提案机制)

源码优化

源码结构(Monorepo)

  • Vue2:源码集中在 src/,按功能子目录划分:compiler/core/platforms/server/sfc/shared
  • 问题:模块耦合度高,难以独立发布与版本管理;测试与类型定义难以按包隔离。
  • Vue3:采用 Monorepo,将功能拆分到多个包(如 reactivity/runtime-core/runtime-dom/compiler-*),每包具备独立的 API、类型与测试。
  • 收益:
    • 责任边界清晰,可插拔能力更强,发布与回滚更精细。
    • 用户可按需引入子包,结合 ESM 与 tree-shaking 降低最终体积。
Monorepo 架构示意

TypeScript 重构

  • 演进:Vue1 纯 JS → Vue2 使用 Flow → Vue3 全面拥抱 TypeScript。
  • 优势:静态类型提升 API 设计严谨性;更佳的 IDE 自动补全与类型提示;公共类型复用与约束更一致。
  • 对开发者的影响:
    • defineComponent/PropType 等模式让组件的 props/emit/slots 具备良好类型推断。
    • 组合式 API(ref/reactive/computed/watch)在 TS 下有明确的类型语义与约束。

性能优化

源码体积与构建

  • 移除冷门特性:如 filter/inline-template 等,减少运行时负担。
  • 构建工具:生产环境使用 Rollup,天然偏向库构建与 ESM,利于静态分析与 tree-shaking。
  • Tree-shaking:依赖于 ES 模块静态结构,移除未被引用的导出,缩减最终包体积。
js
// Vue3:从子包按需引入,利于 tree-shaking
import { ref, computed } from "vue";
// Vue2:整体引入,静态分析粒度较粗
import Vue from "vue";

响应式系统

  • Vue2 使用 Object.defineProperty 劫持属性读写,难以覆盖新增/删除属性、数组索引与长度变化。
  • Vue3 使用 Proxy 劫持对象级别的访问:可感知属性新增/删除、数组操作、Map/Set 等结构;覆盖更完备,性能更佳。
  • 组合式 API 与响应式家族:reactive/readonly/ref/shallowReactive/shallowRef;副作用注册与调度由 effect 完成。

详细内容参考文章Vue3 响应式变化

编译器优化

  • 静态提升(hoistStatic):将完全静态的节点常量化,避免每次渲染重复创建。
  • 预字符串化:将大文本节点在编译期拼接为常量字符串,减少运行期开销。
  • 事件处理函数缓存:对不变的事件回调进行缓存,避免更新阶段的重复绑定与比较。
  • Block Tree:以「可变边界」划分子树,更新时仅遍历带 PatchFlags 的可变块,缩小 diff 范围。
  • PatchFlags:在编译期标记节点的可变属性,如 CLASS/STYLE/TEXT/PROPS 等,使运行期能精准更新。

diff 算法

  • Vue2 双端 diff:从头尾同时比较,对移动与插入场景处理较为保守。
  • Vue3 快速 diff:针对有 key 的子节点使用更优化的对齐策略,结合最长递增子序列(LIS)定位最少移动集,减少 DOM 操作次数。

语法 API 优化

Options API → Composition API

  • Vue2 使用 Options API:将逻辑按 data/methods/computed/props 分散在不同选项中。
  • Vue3 推荐 Composition API:围绕「功能单元」组织相关状态与方法,读写更集中,复用粒度更细。
  • <script setup>:在 SFC 中以更简洁的语法使用组合式 API,编译后自动暴露到模板。
Composition API 组织逻辑

mixin → 组合式函数

  • mixin 缺点:
    • 数据来源不清晰(属性从何处注入难以追踪)。
    • 命名冲突风险(同名属性/方法覆盖)。
    • 隐式耦合(多个 mixin 之间交互难以显式表达)。
  • 组合式函数:通过普通函数返回状态与方法,依赖显式传参,来源明确、可测试性更好。
js
// 组合式复用示例
function useCounter(initial = 0) {
  const count = ref(initial);
  const inc = () => (count.value += 1);
  return { count, inc };
}

应用创建与隔离(new Vue → createApp)

  • Vue2 通过 new Vue() 创建应用:调用构造函数的静态方法(use/mixin/component)会对页面内所有应用生效,难以实现隔离。
  • Vue3 通过 createApp(root) 创建应用:所有与应用相关的注册都挂在应用实例上,彼此隔离。
js
// Vue2(全局污染风险)
Vue.use(...);
Vue.mixin(...);
Vue.component(...);
new Vue({}).$mount('#app1');
new Vue({}).$mount('#app2');

// Vue3(应用级隔离)
import { createApp } from 'vue';
createApp(App).use(...).mixin(...).component(...).mount('#app1');
createApp(App).mount('#app2');

面试题:为什么 Vue3 去掉了 Vue 构造函数?

  1. 静态方法全局生效,无法隔离多应用配置。
  2. 构造函数承载过多功能,不利于 tree-shaking;Vue3 以普通函数导出以便按需引入。
  3. 明确区分「应用」与「组件实例」两个概念;createApp 返回的是应用对象,其方法作用于整个应用,而非特殊组件。

其他重要变化

  • Fragment/Teleport/Suspense 等内置能力增强组件表达力。
  • 生命周期名称更新与并存。

引入 RFC

什么是 RFC

RFC(Request For Comments)是一种公开的提案流程,用于收集社区对新功能或重大更改的意见。 它以文档形式描述动机、设计、实现细节与兼容性影响,并在充分讨论后决定采纳或拒绝。

一份 RFC 通常包含
  1. 标题:简短描述提案目的
  2. 摘要:说明内容与动机
  3. 动机:为何需要、解决何问题
  4. 详细设计:核心设计与实现路径
  5. 潜在问题与替代方案:权衡与备选
  6. 不兼容变更:兼容性与迁移策略
价值与影响
  • 决策透明:社区可参与功能讨论,理解取舍。
  • 迭代稳健:在设计落地前充分审视边界与兼容性。
  • 典型提案:Composition API、Teleport/Suspense、<script setup> 等均通过 RFC 讨论与演进。

面试题

说一下 Vue3 相比 Vue2 有什么新的变化?

参考答案:

  • 源码优化:使用 TypeScript 重构核心代码,采用 Monorepo 管理多包,子包具备独立 API/类型/测试与发布能力,按需引入更容易。
  • 性能优化:响应式从 Object.defineProperty 升级为 Proxy;编译器引入静态提升、PatchFlags、Block Tree、事件缓存、预字符串化;运行期使用更优的快速 diff 算法,整体性能显著提升。
  • 语法 API:引入 Composition API 与 <script setup>,围绕功能集中组织逻辑,复用粒度更细;以组合式函数替代 mixin 的隐式注入;通过 createApp 提供应用级隔离,杜绝全局构造函数带来的污染。
  • RFC 流程:核心团队通过 RFC 与社区协作,在公开的提案、讨论与修订中推进重大功能与变更,提升稳定性与透明度。

总结:Vue3 在工程化、性能与开发体验上进行了系统性升级。新项目推荐直接采用 Vue3,以获得更好的类型支持、更高的性能与更清晰的代码组织方式。