📊 总体架构对比
graph TB
subgraph "Vue 2 架构"
V2[Vue 2 Constructor]
V2 --> V2Obs[Observer 响应式系统]
V2 --> V2Comp[Options API 组件]
V2 --> V2VDom[VNode 虚拟DOM]
V2 --> V2Compiler[Template 编译器]
V2Obs --> V2DefProp[Object.defineProperty]
V2Comp --> V2Life[生命周期钩子]
V2VDom --> V2Patch[Patch 算法]
end
subgraph "Vue 3 架构"
V3[Vue 3 createApp]
V3 --> V3Proxy[Proxy 响应式系统]
V3 --> V3Comp[Composition API]
V3 --> V3VDom[VNode with PatchFlags]
V3 --> V3Compiler[优化编译器]
V3Proxy --> V3Reactive[reactive/ref]
V3Comp --> V3Setup[setup 函数]
V3VDom --> V3StaticHoist[静态提升]
end
🔄 响应式系统对比
Vue 2 响应式原理
核心实现:Object.defineProperty
// Vue 2 源码:src/core/observer/index.ts
export function defineReactive(
obj: object,
key: string,
val?: any,
customSetter?: Function | null,
shallow?: boolean,
mock?: boolean
) {
const dep = new Dep()
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter() {
const value = getter ? getter.call(obj) : val
if (Dep.target) {
dep.depend() // 依赖收集
}
return value
},
set: function reactiveSetter(newVal) {
if (newVal === value || (newVal !== newVal && value !== value)) {
return
}
val = newVal
dep.notify() // 派发更新
}
})
}
Vue 3 响应式原理
核心实现:Proxy
// Vue 3 源码:packages/reactivity/src/reactive.ts
export function reactive(target: object) {
return createReactiveObject(
target,
false,
mutableHandlers,
mutableCollectionHandlers,
reactiveMap
)
}
// packages/reactivity/src/baseHandlers.ts
class MutableReactiveHandler extends BaseReactiveHandler {
get(target: object, key: string | symbol, receiver: object) {
// 依赖收集
track(target, TrackOpTypes.GET, key)
const res = Reflect.get(target, key, receiver)
// 深度响应式
if (isObject(res)) {
return reactive(res)
}
return res
}
set(target: object, key: string | symbol, value: unknown, receiver: object) {
const oldValue = target[key]
const result = Reflect.set(target, key, value, receiver)
// 派发更新
if (hasChanged(value, oldValue)) {
trigger(target, TriggerOpTypes.SET, key, value, oldValue)
}
return result
}
}
响应式系统对比图
flowchart LR
subgraph "Vue 2 响应式"
A[Object.defineProperty] --> B[getter/setter]
B --> C[Dep 依赖收集]
C --> D[Watcher 观察者]
D --> E[组件更新]
F["❌ 限制"]
F --> G["无法检测数组索引变化"]
F --> H["无法检测对象属性添加/删除"]
F --> I["需要递归遍历所有属性"]
end
subgraph "Vue 3 响应式"
J[Proxy] --> K["拦截所有操作"]
K --> L[track 依赖收集]
L --> M[trigger 派发更新]
M --> N[组件更新]
O["✅ 优势"]
O --> P["完整的数组支持"]
O --> Q["动态属性添加/删除"]
O --> R["懒代理,按需响应式"]
end
🧩 组件系统对比
Vue 2 Options API
// Vue 2 组件定义
export default {
data() {
return {
count: 0,
message: 'Hello'
}
},
computed: {
doubleCount() {
return this.count * 2
}
},
methods: {
increment() {
this.count++
}
},
mounted() {
console.log('组件已挂载')
}
}
Vue 3 Composition API
// Vue 3 组件定义
import { ref, computed, onMounted } from 'vue'
export default {
setup() {
const count = ref(0)
const message = ref('Hello')
const doubleCount = computed(() => count.value * 2)
const increment = () => {
count.value++
}
onMounted(() => {
console.log('组件已挂载')
})
return {
count,
message,
doubleCount,
increment
}
}
}
组件系统架构对比
graph TD
subgraph "Vue 2 组件系统"
A[Vue Constructor] --> B[initMixin]
A --> C[stateMixin]
A --> D[eventsMixin]
A --> E[lifecycleMixin]
A --> F[renderMixin]
G[Options API] --> H[data]
G --> I[computed]
G --> J[methods]
G --> K[生命周期钩子]
L["❌ 问题"]
L --> M["逻辑分散"]
L --> N["复用困难"]
L --> O["TypeScript 支持差"]
end
graph TD
subgraph "Vue 3 组件系统"
P[createApp] --> Q[ComponentInternalInstance]
Q --> R[setup 函数]
S[Composition API] --> T[ref/reactive]
S --> U[computed]
S --> V[生命周期 hooks]
S --> W[自定义 hooks]
X["✅ 优势"]
X --> Y["逻辑聚合"]
X --> Z["更好的复用"]
X --> AA["完整 TypeScript 支持"]
end
🔄 生命周期对比
生命周期映射表
| Vue 2 | Vue 3 | 说明 |
|---|---|---|
| beforeCreate | setup() | 组件创建前 |
| created | setup() | 组件创建后 |
| beforeMount | onBeforeMount | 挂载前 |
| mounted | onMounted | 挂载后 |
| beforeUpdate | onBeforeUpdate | 更新前 |
| updated | onUpdated | 更新后 |
| beforeDestroy | onBeforeUnmount | 卸载前 |
| destroyed | onUnmounted | 卸载后 |
| errorCaptured | onErrorCaptured | 错误捕获 |
| - | onRenderTracked | 渲染跟踪 |
| - | onRenderTriggered | 渲染触发 |
生命周期实现对比
sequenceDiagram
participant V2 as Vue 2 实例
participant V3 as Vue 3 组件
Note over V2: Options API 生命周期
V2->>V2: beforeCreate
V2->>V2: created
V2->>V2: beforeMount
V2->>V2: mounted
Note over V3: Composition API 生命周期
V3->>V3: setup()
V3->>V3: onBeforeMount()
V3->>V3: onMounted()
Note right of V3: 更灵活的钩子注册
🎨 虚拟DOM对比
Vue 2 VNode 结构
// Vue 2 VNode 类
export default class VNode {
tag?: string
data: VNodeData | undefined
children?: Array<VNode> | null
text?: string
elm: Node | undefined
context?: Component
componentOptions?: VNodeComponentOptions
componentInstance?: Component
constructor(
tag?: string,
data?: VNodeData,
children?: Array<VNode> | null,
text?: string,
elm?: Node,
context?: Component,
componentOptions?: VNodeComponentOptions
) {
// 初始化属性
}
}
Vue 3 VNode 优化
// Vue 3 VNode 接口
export interface VNode<
HostNode = RendererNode,
HostElement = RendererElement,
ExtraProps = { [key: string]: any }
> {
type: VNodeTypes
props: (VNodeProps & ExtraProps) | null
key: string | number | symbol | null
ref: VNodeNormalizedRef | null
children: VNodeNormalizedChildren
component: ComponentInternalInstance | null
// 优化标记
patchFlag: number
dynamicProps: string[] | null
dynamicChildren: VNode[] | null
}
虚拟DOM优化对比
graph LR
subgraph "Vue 2 虚拟DOM"
A["全量 diff"] --> B["递归比较所有节点"]
B --> C["性能瓶颈"]
D["静态节点"] --> E["每次都参与 diff"]
end
subgraph "Vue 3 虚拟DOM"
F["PatchFlags 标记"] --> G["只 diff 动态内容"]
G --> H["性能提升"]
I["静态提升"] --> J["静态节点缓存"]
J --> K["Block Tree"]
K --> L["靶向更新"]
end
⚡ 编译器优化对比
Vue 2 编译流程
flowchart LR
A[Template] --> B[Parse AST]
B --> C[Optimize]
C --> D[Generate Code]
D --> E[Render Function]
F["优化有限"]
F --> G["标记静态节点"]
F --> H["静态根节点优化"]
Vue 3 编译优化
flowchart LR
A[Template] --> B[Parse AST]
B --> C[Transform]
C --> D["多种优化"]
D --> E[Generate Code]
E --> F[Optimized Render]
G["编译时优化"]
G --> H["静态提升"]
G --> I["PatchFlag 标记"]
G --> J["内联组件 props"]
G --> K["死代码消除"]
📦 打包体积对比
体积对比图
Vue 2:
- Runtime Only: ~34KB
- Runtime + Compiler: ~76KB
- 完整版本: ~120KB
Vue 3:
- Runtime Only: ~16KB (Tree-shaking 后)
- Runtime + Compiler: ~47KB
- 完整版本: ~84KB
🚀 性能对比
性能提升图表
性能优化点
| 优化项 | Vue 2 | Vue 3 | 提升 |
|---|---|---|---|
| 响应式系统 | Object.defineProperty | Proxy | 2x |
| 虚拟DOM | 全量 diff | PatchFlag + 静态提升 | 2.5x |
| 编译优化 | 基础优化 | 多重编译时优化 | 3x |
| Tree-shaking | 不支持 | 完全支持 | 50% 体积减少 |
| TypeScript | 部分支持 | 原生支持 | 完整类型推导 |
🔧 API 变化总结
新增 API
Composition API:
ref()/reactive()computed()watch()/watchEffect()onMounted()等生命周期钩子provide()/inject()defineComponent()defineProps()/defineEmits()
工具函数:
toRef()/toRefs()unref()isRef()/isReactive()nextTick()createApp()
移除的 API
Vue.config.productionTipVue.extend()Vue.component()全局注册方式改变$children实例属性$listeners(合并到$attrs)- 过滤器 (Filters)
- 内联模板 (inline-template)
🎯 迁移建议
渐进式迁移策略
flowchart TD
A["Vue 2 项目"] --> B{"评估项目规模"}
B -->|小型项目| C["直接升级 Vue 3"]
B -->|中型项目| D["使用 @vue/compat"]
B -->|大型项目| E["分模块迁移"]
C --> F["更新依赖"]
D --> G["兼容模式运行"]
E --> H["新功能用 Vue 3"]
F --> I["测试验证"]
G --> J["逐步移除兼容"]
H --> K["老功能保持 Vue 2"]
I --> L["部署上线"]
J --> L
K --> M["最终统一"]
M --> L
关键迁移步骤
-
依赖更新
npm install vue@next npm install @vue/compiler-sfc@next -
构建工具配置
// vite.config.js import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' export default defineConfig({ plugins: [vue()] }) -
入口文件修改
// Vue 2 import Vue from 'vue' import App from './App.vue' new Vue({ render: h => h(App) }).$mount('#app') // Vue 3 import { createApp } from 'vue' import App from './App.vue' createApp(App).mount('#app')
📊 总结对比表
| 特性 | Vue 2 | Vue 3 | 优势 |
|---|---|---|---|
| 响应式 | Object.defineProperty | Proxy | 更强大的拦截能力 |
| 组件API | Options API | Composition API | 更好的逻辑复用 |
| TypeScript | 部分支持 | 原生支持 | 完整类型推导 |
| 性能 | 基准 | 2-3x 提升 | 编译时优化 |
| 体积 | 较大 | 更小 | Tree-shaking |
| 生态 | 成熟稳定 | 快速发展 | 向后兼容 |
| 学习成本 | 较低 | 中等 | 需要学习新概念 |
🔮 未来展望
Vue 3 的优势:
- 更好的性能表现
- 更强的 TypeScript 支持
- 更灵活的组合式 API
- 更小的打包体积
- 更好的 Tree-shaking
建议:
- 新项目直接使用 Vue 3
- 现有项目可考虑渐进式迁移
- 充分利用 Composition API 的优势
- 关注 Vue 3 生态的发展
本文档基于 Vue 2.7.x 和 Vue 3.4.x 版本源码分析整理 欢迎指正错误