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. 迁移先改小组件,逐步替换,风险更低

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


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

相关推荐
mldong5 小时前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排6 小时前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60616 小时前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角7 小时前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!7 小时前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰8 小时前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端
mayaairi9 小时前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen10 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马10 小时前
AI源码分析:拆解模型底层实现逻辑
前端
BillKu10 小时前
全局样式变量:CSS 自定义属性(--border-color)和SCSS 变量($border-color)的说明
javascript·css·scss