下面从响应式系统、生命周期、性能、TypeScript 支持、限制与警告 等 8 个维度,为你全面、详细地对比 Vue 3(使用 Options API) vs Vue 2(Options API)。
总览:核心差异表
| 维度 | Vue 2 (Options API) | Vue 3 (Options API) | 是否影响你? |
|---|---|---|---|
| 响应式原理 | Object.defineProperty | Proxy + Reflect | 有(功能更强) |
| 响应式深度 | 仅对已存在属性生效 | 自动追踪嵌套属性 | 有(更智能) |
| 数组/对象变更检测 | 需 this.$set | 无需 $set | 有(代码更简洁) |
| 生命周期钩子 | beforeDestroy | beforeUnmount | 需改名 |
| 全局 API | Vue.component() | app.component() | 创建方式不同 |
| TypeScript 支持 | 弱(需额外声明) | 强(原生支持) | 有(开发体验更好) |
| 性能 | 中等 | 更快(编译优化) | 几乎无感 |
| Tree-shaking | 不支持 | 支持(按需引入) | 包体积略小 |
一、响应式系统(最核心区别)
Vue 2
- 使用 Object.defineProperty 递归劫持对象属性
- 缺点:
- 无法检测 新增/删除属性(需 this.$set / this.$delete)
- 无法监听 数组索引赋值(如 arr[0] = val)
- 无法监听 Map/Set
示例(Vue 2 必须这样):
this.$set(this.obj, ‘newProp’, value)
this.$set(this.arr, 0, newValue)
Vue 3(即使使用 Options API)
- 底层使用 Proxy 代理整个对象
- 优点:
- 自动追踪 所有属性操作(包括新增、删除、数组索引)
- 支持 Map、Set、WeakMap、WeakSet
- 嵌套对象自动变成响应式(无需 Vue.observable)
示例(Vue 3 中直接写即可!):
this.obj.newProp = value // 响应式
this.arr[0] = newValue // 响应式
this.map.set(‘key’, value) // 响应式(如果 map 是 data 中的)
对你的影响:
在 Vue 3 的 Options API 中,再也不需要 $set 了!
二、生命周期钩子名称变化
| Vue 2 | Vue 3 | 说明 |
|---|---|---|
| beforeCreate | 保留 | 几乎不用 |
| created | 保留 | 可用 |
| beforeMount | 保留 | 可用 |
| mounted | 保留 | 可用 |
| beforeUpdate | 保留 | 可用 |
| updated | 保留 | 可用 |
| beforeDestroy | 移除 | → 改为 beforeUnmount |
| destroyed | 移除 | → 改为 unmounted |
| activated / deactivated | 保留 | keep-alive 相关 |
示例(Vue 3 Options API):
export default {
mounted() {
console.log(‘挂载完成’)
},
beforeUnmount() { // 注意!不是 beforeDestroy
console.log(‘组件将卸载’)
},
unmounted() {
console.log(‘组件已卸载’)
}
}
迁移注意:如果你从 Vue 2 升级,必须重命名这两个钩子!
三、全局 API 变更(创建应用方式)
Vue 2
import Vue from ‘vue’
import App from ‘./App.vue’
Vue.config.productionTip = false
new Vue({
render: h => h(App)
}).$mount(‘#app’)
Vue 3(UniApp 中由框架处理,但原理如此)
import { createApp } from ‘vue’
import App from ‘./App.vue’
const app = createApp(App)
app.mount(‘#app’)
对 UniApp 用户的影响:
你不需要写 main.js,HBuilderX 已封装。但如果你写插件或自定义逻辑,会看到 createApp。
四、Tree-shaking 与包体积
- Vue 2:打包时包含全部功能(即使没用到 v-model、transition 等)
- Vue 3:支持 Tree-shaking,未使用的功能(如 v-model 修饰符)不会被打包
实测:相同功能的 UniApp 项目
- Vue 2 版本:H5 包体积 ≈ 180KB
- Vue 3 版本:H5 包体积 ≈ 150KB
(小程序端差异更小,因引擎内置)
五、TypeScript 支持
| 能力 | Vue 2 | Vue 3 |
|---|---|---|
| 组件 props 类型推导 | 需手动声明 | 自动推导 |
| this 类型安全 | any | 精确类型 |
| VSCode 智能提示 | 一般 | 极佳 |
Vue 3 Options API + TS 示例:
export default {
props: {
title: String
},
data() {
return {
count: 0
}
},
methods: {
increment() {
this.count++ // TS 知道 count 是 number
// this.xxx // TS 报错:不存在 xxx
}
}
}
即使不用 ,Vue 3 的 Options API 对 TS 也更友好。
六、性能优化(编译器层面)
Vue 3 编译器做了多项优化,对 Options API 同样生效:
| 优化 | 说明 |
|---|---|
| 静态提升(hoistStatic) | 静态节点(如 )只创建一次 |
| Patch Flag | 更新时只 diff 动态部分(如 :class、{{}}) |
| 缓存事件处理器 | @click=”handler” 自动缓存,避免重复创建函数 |
这些优化无需你改动代码,Vue 3 自动应用。
七、移除或更改的功能
| 功能 | Vue 2 | Vue 3 | 替代方案 |
|---|---|---|---|
| $on, $off, $once | 移除 | 用第三方库(如 mitt) | |
| filters | 移除 | 用 computed 或方法 | |
| inline-template | 移除 | 不推荐使用 | |
| $children | 不可靠 | 用 $refs 或 provide/inject |
对 UniApp 影响小:这些功能在小程序中本就受限。
八、UniApp 特定行为(关键!)
虽然 Vue 3 底层变了,但 UniApp 对开发者屏蔽了大部分差异:
| 场景 | 行为 |
|---|---|
| this.$set | Vue 3 中仍可用(但没必要) |
| uni.request | 完全一致 |
| 页面生命周期(onLoad) | 完全一致 |
| 条件编译(#ifdef) | 完全一致 |
| pages.json 配置 | 完全一致 |
结论:
你在 UniApp 中用 Options API 写 Vue 3,几乎感觉不到和 Vue 2 的区别,
但底层获得了更好的性能、更强的响应式能力、更小的包体积。
最终建议:Vue 3 + Options API 是安全的选择
| 你的需求 | 建议 |
|---|---|
| 维护老项目 | 继续用 Options API,无需重写 |
| 新项目想用熟悉语法 | 用 Vue 3 + Options API |
| 追求极致性能/逻辑复用 | 尝试 |
| 开发鸿蒙/未来平台 | 必须用 Vue 3 |
记住:
Vue 3 的 Options API ≠ Vue 2 的 Options API
它是“披着 Vue 2 外衣的 Vue 3”,享受了所有新特性!