Vue2 升 Vue3 避坑指南:10个高频迁移错误与正确姿势

张开发
2026/4/7 16:21:36 15 分钟阅读

分享文章

Vue2 升 Vue3 避坑指南:10个高频迁移错误与正确姿势
一、前言Vue2 升 Vue3 是每个 Vue 项目的必经之路Vue2 已于 2023 年 12 月 31 日停止维护。如果你的项目还在 Vue2是时候升级了。本文总结了真实项目迁移中最高频的 10 个坑每个坑都附上错误写法和正确解法。二、Options API 转 Composition API 10 大坑坑1data 函数返回值的响应式// ❌ Vue2 写法 export default { data() { return { count: 0, user: { name: } } } } // ✅ Vue3 Composition API import { ref, reactive } from vue const count ref(0) const user reactive({ name: }) // 注意reactive 解构会丢失响应性用 toRefs const { name } toRefs(user)坑2this 消失了// ❌ Vue2 methods: { fetchUser() { this.loading true // this 可以访问所有 data/computed/methods api.getUser().then(res { this.user res }) } } // ✅ Vue3 const loading ref(false) const user ref(null) async function fetchUser() { loading.value true // 直接用变量没有 this user.value await api.getUser() loading.value false }坑3watch 不再自动深度监听对象// Vue2watch 对象属性会触发 watch: { user.name(val) { ... } } // Vue3必须明确写 deep 或 watch 具体属性 watch(() user.name, (val) { ... }) // 或者 watch(user, (val) { ... }, { deep: true })坑4生命周期钩子改名Vue2Vue3beforeCreatesetup() 本身createdsetup() 本身beforeMountonBeforeMountmountedonMountedbeforeUpdateonBeforeUpdateupdatedonUpdatedbeforeDestroyonBeforeUnmountdestroyedonUnmounted坑5$emit 需要先 defineEmits!-- ❌ Vue2 直接用 this.$emit -- script export default { methods: { submit() { this.$emit(submit, this.form) } } } /script !-- ✅ Vue3 必须先 defineEmits -- script setup const emit defineEmits([submit]) function submit() { emit(submit, form.value) } /script坑6$attrs 行为变了Vue3 的$attrs包含 class、style 和所有未在 props 中声明的属性Vue2 中 class/style 不在 $attrs 里。!-- Vue3禁用自动透传 $attrs手动控制 -- script setup defineOptions({ inheritAttrs: false }) /script template div classwrapper input v-bind$attrs / !-- 只把 attrs 绑到 input不绑到根元素 -- /div /template坑7v-model 语法变化!-- Vue2 -- MyInput v-modelvalue / !-- 等价于 :valuevalue inputvalue $event -- !-- Vue3 -- MyInput v-modelvalue / !-- 等价于 :modelValuevalue update:modelValuevalue $event -- !-- Vue3 子组件接收 -- script setup defineProps([modelValue]) const emit defineEmits([update:modelValue]) /script !-- Vue3 支持多个 v-model -- UserForm v-model:namename v-model:ageage /坑8过滤器filters被移除// ❌ Vue2 filters filters: { formatDate(val) { return dayjs(val).format(YYYY-MM-DD) } } // 模板中{{ date | formatDate }} // ✅ Vue3 改用 computed 或普通函数 function formatDate(val) { return dayjs(val).format(YYYY-MM-DD) } // 模板中{{ formatDate(date) }}坑9Vuex 换成 Pinia// ❌ Vuex 4还能用但推荐迁移 const store createStore({ state: { count: 0 }, mutations: { increment(state) { state.count } } }) // ✅ PiniaVue3 官方推荐 import { defineStore } from pinia export const useCounterStore defineStore(counter, () { const count ref(0) function increment() { count.value } return { count, increment } })坑10Vue Router 4 的 history 配置// ❌ Vue2 const router new VueRouter({ mode: history, routes }) // ✅ Vue3 import { createRouter, createWebHistory } from vue-router const router createRouter({ history: createWebHistory(), // 替代 mode: history routes })三、迁移建议分步迁移不要一次性全改用vue/compat兼容模式逐步迁移先升依赖Vue Router、Vuex/Pinia、UI 组件库都要同步升级TypeScript 支持Vue3 TypeScript 体验远好于 Vue2迁移时顺手加上用官方迁移工具vue-migration-helper可以扫描代码中的 Vue2 特性Vue2 升 Vue3 避坑指南收藏备用关注我后续更新《Vue3完整迁移实战》系列。觉得有用点赞收藏关注后续持续更新《框架迁移避坑》系列React↔Vue3↔Angular 全覆盖。标签vue3 | vue2 | 迁移 | 前端 | 避坑

更多文章