Vue2 迁移 Vue3 避坑指南

前言:Vue3 凭借更好的性能、Proxy 响应式、Composition API 以及完善的 TS 支持,已经成为前端主流版本。但很多同学在从 Vue2 迁移到 Vue3 时,总会因为 API 变化、语法差异踩各种坑。

本文整理了 Vue2 升级 Vue3 最核心的 5 个变化,搭配完整可运行代码案例,帮你一次性避开 90% 常见坑,无痛完成迁移。


一、API 风格巨变:Options API → Composition API

这是 Vue2 到 Vue3 最核心、最直观的区别。

1.1 核心区别

  • Vue2 :按 datamethodscomputedwatch 分类写代码,逻辑容易分散。
  • Vue3 :推荐使用 Composition API + <script setup>,逻辑聚合、复用性更强、代码更简洁。

1.2 实战对比

Vue2 写法
vue 复制代码
<template>
  <div>
    <input v-model="count" type="number" />
    <button @click="addCount">加 1</button>
    <p>双倍值:{{ doubleCount }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      count: 0
    }
  },
  computed: {
    doubleCount() {
      return this.count * 2
    }
  },
  methods: {
    addCount() {
      this.count++
    }
  },
  mounted() {
    console.log('mounted', this.count)
  }
}
</script>
Vue3 <script setup> 写法
vue 复制代码
<template>
  <div>
    <input v-model="count" type="number" />
    <button @click="addCount">加 1</button>
    <p>双倍值:{{ doubleCount }}</p>
  </div>
</template>

<script setup>
import { ref, computed, onMounted } from 'vue'

// 响应式变量
const count = ref(0)

// 计算属性
const doubleCount = computed(() => count.value * 2)

// 方法
const addCount = () => {
  count.value++
}

// 生命周期
onMounted(() => {
  console.log('mounted', count.value)
})
</script>

1.3 必避坑点

  1. setup 内部没有 this ,不能写 this.xxx
  2. ref 变量在 JS 中必须用 .value,模板中不用
  3. 优先使用 <script setup>,代码量减少 50%

二、生命周期函数改名与调整

Vue3 对生命周期做了语义化优化,大部分只是换个名字。

2.1 对应关系表

Vue2 生命周期 Vue3 组合式 API 说明
beforeCreate setup 内部 已合并
created setup 内部 已合并
beforeMount onBeforeMount -
mounted onMounted -
beforeUpdate onBeforeUpdate -
updated onUpdated -
beforeDestroy onBeforeUnmount 改名
destroyed onUnmounted 改名

2.2 避坑点

  • 不要再写 beforeDestroydestroyed,会直接失效
  • 所有生命周期都需要从 vue 中导入使用

三、全局 API 重构:不再污染全局 Vue

Vue2 全局操作容易污染,Vue3 改用 createApp 实例化应用。

3.1 Vue2 全局挂载

js 复制代码
import Vue from 'vue'
import axios from 'axios'
Vue.prototype.$axios = axios

组件内使用:

js 复制代码
this.$axios.get(...)

3.2 Vue3 标准写法(生产推荐)

main.js

js 复制代码
import { createApp } from 'vue'
import App from './App.vue'
import axios from 'axios'

const app = createApp(App)

// 全局 provide
app.provide('$axios', axios)

app.mount('#app')

组件内使用:

js 复制代码
import { inject } from 'vue'
const $axios = inject('$axios')

3.3 避坑点

  • ❌ 不要用 Vue.prototype,Vue3 没有全局 Vue
  • ❌ 不要在生产用 getCurrentInstance,官方不推荐
  • ✅ 全局共享优先使用 provide / inject 或 Pinia

四、v-model 全面升级:更强大、更简洁

Vue2 的 v-model 本质是 value + input,Vue3 重新设计,支持多绑定。

4.1 Vue2 自定义 v-model

vue 复制代码
<template>
  <input :value="value" @input="$emit('input', $event.target.value)" />
</template>

<script>
export default {
  props: ['value']
}
</script>

4.2 Vue3 标准写法

vue 复制代码
<template>
  <input
    :value="modelValue"
    @input="$emit('update:modelValue', $event.target.value)"
  />
</template>

<script setup>
defineProps(['modelValue'])
defineEmits(['update:modelValue'])
</script>

4.3 Vue3.4+ 超简写法(defineModel)

vue 复制代码
<template>
  <input v-model="model" />
</template>

<script setup>
import { defineModel } from 'vue'
const model = defineModel()
</script>

4.4 避坑点

  • 自定义组件 v-model 不再用 value,改用 modelValue
  • Vue2 .sync 修饰符已废弃,直接用 v-model:xxx
  • 支持多个 v-model 同时绑定

五、响应式原理升级:Object.defineProperty → Proxy

这是底层最大升级,解决了 Vue2 很多响应式缺陷。

5.1 Vue2 缺陷

  • 无法监听数组下标修改
  • 无法监听对象新增属性
  • 必须用 this.$set / Vue.set

5.2 Vue3 天然支持

vue 复制代码
<script setup>
import { reactive } from 'vue'

// 数组直接修改下标,依然响应
const list = reactive(['a', 'b', 'c'])
list[0] = 'hello'

// 对象新增属性,依然响应
const user = reactive({ name: '张三' })
user.age = 20
</script>

5.3 避坑点

  • Vue3 不需要 $set,直接赋值即可
  • 基本类型用 ref,对象/数组用 reactive
  • 不要解构 reactive 对象,会丢失响应式

六、Vue2 迁移 Vue3 实用工具

  1. vue-codemod
    官方批量转换工具,自动改语法:

    bash 复制代码
    npm install -g vue-codemod
    vue-codemod vue3-volar ./src
  2. Vue DevTools
    必须使用 Vue3 专用版本

  3. Vite 替代 Vue CLI,构建速度提升明显


七、总结(迁移速记版)

  1. 放弃 Options API,拥抱 <script setup>
  2. 生命周期:destroyedonUnmounted
  3. 全局挂载改用 app.provide 或 Pinia
  4. 自定义 v-model 改为 modelValue + update:modelValue
  5. 响应式基于 Proxy,数组/对象直接修改即可
  6. 迁移先改小组件,逐步替换,风险更低

本文从实际项目迁移经验总结而来,覆盖绝大多数业务场景。如果你在迁移中遇到其他奇怪问题,欢迎在评论区交流!


版权声明:本文为原创技术博客,未经授权禁止转载、搬运、洗稿。如需转载请联系作者并注明原文出处。

相关推荐
进击的尘埃2 小时前
Signals 跨框架收敛:TC39 提案、Solid、Angular、Preact 的实现差异与调度策略对比
javascript
程序员陆业聪2 小时前
工程师的瓶颈,已经不是代码了
前端
毛骗导演2 小时前
@tencent-weixin/openclaw-weixin 源码ContextToken 持久化改造:实现微信自定义消息发送能力
前端·架构
爱丽_2 小时前
Pinia 状态管理:模块化、持久化与“权限联动”落地
java·前端·spring
进击的尘埃2 小时前
从多仓到 Monorepo 的渐进式迁移:Git 历史保留、依赖收敛与缓存调优
javascript
SuperEugene2 小时前
TypeScript+Vue 实战:告别 any 滥用,统一接口 / Props / 表单类型,实现类型安全|编码语法规范篇
开发语言·前端·javascript·vue.js·安全·typescript
我是永恒3 小时前
上架一个跨境工具导航网站
前端
电子羊3 小时前
Spec 编程工作流文档
前端
GISer_Jing3 小时前
从CLI到GUI桌面应用——前端工程化进阶之路
前端·人工智能·aigc·交互