前端知库

Vue 2 项目如何迁移到 Vue 3?

先升级到 Vue 2.7,用组合式 API 和 <script setup> 改写并清理 filters、$listeners、.sync 等写法;检查组件库、路由和 IE11 等依赖边界;再用 @vue/compat 迁移构建逐项消除警告,同时升级 vue-router 4、Vuex 4 或改用 Pinia。

参考答案

Vue 2 已于 2023-12-31 停止维护,本题 Vue 2 部分以 2.7 为准。通信写法的具体改动见《Vue 2 有哪些组件通信方式?哪些写法在 Vue 3 中被移除或改变?》。

简答

  • 先评估能否迁移:依赖 Vue 2 内部 API 的库、尚无 Vue 3 版本的组件库、必须支持 IE11 的项目,都可能需要暂留 Vue 2。
  • 可以先升级到 Vue 2.7:它内置组合式 API、<script setup> 和 SFC CSS v-bind,能在 Vue 2 上提前改写代码,缩小之后的差异。
  • 正式迁移可用 @vue/compat:它是可配置 Vue 2 兼容行为的 Vue 3 构建,默认以 Vue 2 模式运行,对废弃用法发出警告,可以逐项修复。
  • 主要破坏性变更包括 createApp 取代 new Vue()、组件 v-model 重做并移除 .sync、$listeners/$on/filters 移除、beforeDestroy/destroyed 改名、过渡类名变化等。
  • 生态同步升级:vue-router 4、Vuex 4(或改用官方推荐的 Pinia)、vue-template-compiler 换成 @vue/compiler-sfc。

第一步:评估依赖与环境

迁移构建文档列出了几类限制:

  • 依赖 Vue 2 内部 API 或未公开行为的库,最常见的是访问 VNode 私有属性。
  • 依赖 Vuetify、Quasar、ElementUI 等组件库时,最好等它们的 Vue 3 兼容版本。
  • Vue 3 不支持 IE11,需要支持 IE11 的项目只能留在 Vue 2。
  • 自定义 SSR 迁移成本更高,vue-server-renderer 要换成 @vue/server-renderer。

第二步:在 Vue 2.7 上提前改写

2.7 发布说明列出的移植功能有组合式 API、SFC <script setup>、SFC CSS v-bind,以及 defineComponent() 的类型推断改进。原先使用 @vue/composition-api 插件的项目,把导入改成从 vue 导入即可。

同时要知道 2.7 的边界:组合式 API 基于 Vue 2 的 getter/setter 响应式实现;createApp()、<script setup> 中的顶层 await、模板表达式中的 TypeScript 语法和 Reactivity Transform 没有移植。

这一阶段还可以先清理迁移后不再支持的写法:废弃的具名/作用域插槽语法(2.6 已支持新语法)、filters、$listeners、.sync、EventBus 等。

第三步:用 @vue/compat 切换到 Vue 3

迁移构建文档给出的流程:

  1. 升级工具链:自定义 webpack 升级 vue-loader 到 16;Vue CLI 用 vue upgrade,或改用 Vite。
  2. 在 package.json 中把 vue 升到 3,安装同版本的 @vue/compat,用 @vue/compiler-sfc 替换 vue-template-compiler。
  3. 构建配置中把 vue 别名指向 @vue/compat,并在编译选项中设置 compatConfig: { MODE: 2 }。
JavaScript
// vite.config.js
export default {
  resolve: { alias: { vue: '@vue/compat' } },
  plugins: [
    vue({ template: { compilerOptions: { compatConfig: { MODE: 2 } } } }),
  ],
};
  1. 先修复编译期错误(如 filters),再逐个处理浏览器控制台中的运行时警告。每个警告有 ID,例如 GLOBAL_MOUNT(new Vue() → createApp)、OPTIONS_BEFORE_DESTROY。
  2. 过渡类名变化是唯一没有运行时警告的特性,需要全局搜索 .*-enter、.*-leave 类名。
  3. 改用 createApp 挂载,升级 Vuex 4 和 vue-router 4。
  4. 冲突较大的组件可以通过 compatConfig 选项按组件切换到 Vue 3 行为;警告全部清除后移除迁移构建。

状态管理:Vuex → Pinia

Vue 官方文档说明 Pinia 已承担 Vuex 的角色,Vuex 进入维护模式,新项目推荐 Pinia。迁移时可以先升级 Vuex 4 保证运行,再按模块逐步改写为 Pinia store。

常见追问

  • 为什么不直接重写?大型项目一次性重写风险高;2.7 + 迁移构建允许应用在每一步都保持可运行。
  • 迁移构建能长期使用吗?不能。它的目的是过渡,部分特性在 Vue 2 和 Vue 3 中行为冲突,最终需要移除并切换到正式的 Vue 3。
  • 必须先用组合式 API 吗?不必。Vue 3 仍完整支持选项式 API,组合式 API 是可选的改写方向。