跳到主要内容

创建日期:2026-09-08 | 最近更新:2026-09-08 版本基线:Vue 3.5.42(npm 当前 latest;3.6 仍处 RC)。Vue 2 最终版 2.7.16,OSS 支持已于 2023-12-31 结束。

Vue2 → Vue3 快车道:给熟练 Vue2 开发的心智迁移清单

一句话:Vue 3 不是「另一个框架」,它是把 Vue 2 里你用惯的那套「魔法」换成了更显式的引擎——你会的 80% 直接平移,剩下 20% 是「全局 API 变成 app 实例、Options 换成可组合函数、响应式底层换成 Proxy」。这篇不教语法,只帮你把「旧脑图」一次性迁移过来。

本系列面向熟练 Vue2、想最短路径上 Vue3 并进阶的开发者,共 6 篇:

主题深度
0快车道:心智迁移清单 + 上手路线(本文)导览
1Composition API 与 script setup:ref/reactive/computed/watch、defineProps/defineEmits/defineModel
2迁移深水区:过滤器/$set/fragments/异步组件/Teleport·Suspense/Vuex→Pinia·Router3→4深(实操)
3深 · Vue3 响应式系统拆解:Proxy vs defineProperty、effect、ref 的 .value 真相深(原理)
4深 · 模板编译与渲染优化:Block/patchFlags/静态提升/v-once/v-memo深(原理)
5组合式进阶 × TypeScript × 工程化:composable 范式、Pinia setup store、Router、Vite中上

1. 心智模型:Vue 3 = Vue 2 的三个「换底」

对 Vue2 熟手,与其背 API,不如记住三处换底,其余全是平移:

  1. 入口换底new Vue(...) + 全局 Vue.*createApp(...) + app 实例。所有「全局」注册都收编到 app 上,好处是多实例/微前端/测试不再互相污染。
  2. 代码组织换底data/methods/computed/watch 各占一块的 Options → 一个 setup(或 <script setup>)里用函数拼。组件状态从「对象字段」变成「函数调用」,天然可抽出复用(篇 1、5)。
  3. 响应式换底Object.defineProperty 逐属性劫持 → ES Proxy 整对象代理。所以你不再需要 this.$set/Vue.set/Vue.delete——后加属性、数组下标赋值直接就能响应(篇 3 拆原理)。

对「精通 Vue2」的你:真正要改习惯的只有 API 形状;概念(响应式、组件、指令、插槽、混入→组合式函数)全都一样。

2. 三张「旧→新」对照表(先背这三张,代码就能读了)

① 全局 API / 实例

Vue 2Vue 3说明
new Vue({ el:'#app', ... })createApp(App).mount('#app')组件树挂载
Vue.component(name, comp)app.component(name, comp)局部注册更推荐
Vue.use(plugin, opts)app.use(plugin, opts)插件都要带 app
Vue.directive / mixin / filterapp.directive / app.mixin / 无filter 没了(见下)
Vue.prototype.$http = …app.config.globalProperties.$http = …全局注入改这里
this.$set / this.$delete / Vue.set不需要了Proxy 原生支持增删属性
this.$children / $scopedSlots / $listeners移除$attrs 吸收 $listeners$slots 合并
this.$on/$off/$emit(非父子)移除(用 mitt事件总线不再是内置
this.$refs / $nextTick / $watch(...)都在,$nextTick 也可 import { nextTick }组合式里 watch 是函数

② 组件写法(最重要的一行差异)

// Vue 2
export default {
name: 'Counter',
props: ['init'],
data() { return { count: this.init } },
computed: { double() { return this.count * 2 } },
methods: { inc() { this.count++ } },
watch: { count(v) { console.log('count', v) } },
mounted() { console.log('mounted') },
}
<!-- Vue 3 · <script setup>(推荐写法,下面等价) -->
<script setup>
import { ref, computed, watch, onMounted } from 'vue'
const props = defineProps({ init: Number }) // props 仍声明式
const count = ref(props.init) // data → ref
const double = computed(() => count.value * 2) // computed 变函数
function inc() { count.value++ } // methods → 普通函数
watch(count, v => console.log('count', v))
onMounted(() => console.log('mounted'))
</script>
Vue 2 (Options)Vue 3 (Composition / script setup)
data()ref() / reactive()
computed: {}computed(() => …)
methods: {}普通函数
watch: {}watch(src, cb)
props 选项defineProps()
$emitdefineEmits()
生命周期 mounted/…onMounted/…(在 <script setup> 里直接用)
mixins组合式函数useXxx(),篇 5 重点)

③ 模板/全局差异速查

Vue 2Vue 3
过滤器 {{ x | fmt }} / filters:❌ 移除 → 用 computed/方法或 $filters(全局属性)
v-model 默认 propvalue + inputmodelValue + update:modelValue;支持多个 v-model:titlev-model:title
.sync 修饰符:a.sync并入多 v-modelv-model:a),.sync 移除
v-model$event事件值在 $event值直接是回调参数(组件 emit 的第一个参数)
.native 修饰符@click.native移除 → 组件根节点事件默认透传$attrs
多根节点必须单根支持 fragment(但要手动绑定 $attrs 到想要的那个根)
v-if / v-for 优先级v-forv-if(同元素别混用,包 template
异步组件() => import() 直接defineAsyncComponent(() => import())
<Portal>靠插件内置 <Teleport>
顶层 $slotsthis.$scopedSlots$slots(函数式 slot 语法,篇 1/2)

3. 三天上手路线(对 Vue2 熟练者)

  • 第 1 天:手写平移。 挑一个自己最熟的小组件,用上面②表把它从 Options 改成 <script setup>;再挑一个用到了 $set/过滤器/.sync/事件总线的,看报错清单学会「新 API 在哪」。遇到报错别慌,Vue 3 的告警通常直接告诉你换什么。
  • 第 2 天:补新武器。 过一遍 篇 1defineModeldefineExposeprovide/inject 配合、组合式函数怎么抽。再翻 篇 2 的逐项清单。
  • 第 3 天:吃透原理。篇 3篇 4(有实验输出),把「为什么不用 $set、为什么列表性能好」从「记住」变「理解」。

想先摸手感:npm create vue@latest 选好模板,或看官方交互教程 Vue 3 playground。国内可先 vuejs.cn

4. 开始前想清楚的一件事

要不要保留 Options API? Vue 3 两种都能写,但新代码请直接上 <script setup>

  • 它是官方推荐、类型推导最好、样板最少;
  • Options 写法在 Vue 3 依旧可用,适合渐进迁移期(老组件不动),但别用 Options + mixins 继续写新东西——那等于放弃 Composition 最大的红利(复用与类型)。

迁移节奏建议:从老 Vue2 项目「底朝上」升级先别急——先在新页面/新需求里用 Composition 写,积累手感;真正动老组件时用官方升级工具(vue-router、Vue 官方「Migrate」工具与 迁移指南)辅助。

关联

参考