Vue 2 项目升级 Vue 3 记录

如今 Vue 3 的生态已经逐渐成熟,Vue 2 及相关的配套也都逐渐停止更新,是适合升级的时候了。

Vue 3 的语法还是很容易上手的,对于新项目来说,使用起来没什么问题,也挺好用,但对于 Vue 3 老项目,升级的过程还是稍微有些折腾。

Vue CLI 升级为 Vite

Vue CLI 新版也支持 Vue 3,但毕竟它已经不再更新了,既然升级,还是换成 Vite 吧。

通过 npm init vue@latest 创建 Vue 3 项目,然后将 vite.config.ts 及 eslint 、.eslintrc.cjs .prettierrc.json 等基础文件复制到项目中。

更新后发现 eslint 无法自动修复格式化的内容了,从 eslint 配置文件看到,有一个 @vue/eslint-config-prettier/skip-formatting 设置。

而新版的 package.json 里有一个脚本: "format": "prettier --write src/",看来新版把主要的格式化工作交给 prettier 执行了。

其他的 Vite 设置,在此前 React 项目升级中已有记录: react-scripts 项目升级至 vite

Vue 更新

Vue 提供了一份迁移文档: https://v3-migration.vuejs.org/zh/

列举的非兼容改动还是比较多的,也会产生较多的代码改动量,比如:

  • 全局 API 应用实例
  • v-model 改为 modelValueupdate:modelValue 事件的交互
  • 统一了普通插槽和作用域插槽,需修改 slot 相关旧用法
  • $listeners 合并到 $attrs
  • 移除 v-on.native 修饰符
  • $on$off$once 实例方法已被移
  • 移除了过滤器
  • ...

VSCode 需要安装新版的插件:

  • Vue Language Features (Volar) - 必选
  • TypeScript Vue Plugin (Volar)

如果需要使用 TS,要安装以上两个两个插件,安装后 VSCode 才能识别引入的 Vue 单文件相关类型。同时,项目的 npm 依赖 typescript 也需要更新到最新版,才能正确识别选项式 API 的类型。

Vue Router

迁移文档: https://router.vuejs.org/zh/guide/migration/

总体来说,改动量不大,通过以下格式创建实例:

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: []
})
app.use(router)

另外,transition 和 keep-alive 现在必须通过 v-slot API 在 RouterView 内部使用。

Vuex 升级为 pinia

Pinia 比起 Vuex 更适合组合式 API,对 TS 的支持更好,也是 Vue 未来主推的首选状态管理库。

从 Vuex 迁移: https://pinia.vuejs.org/zh/cookbook/migration-vuex.html

  • mutations 移除了,合并到 actions 里了
  • actions 可以通过 this 获取数据,不需要再接收 state 参数
  • $store 对象没有了,需要用到的地方通过 mapState 获取数据

第三方库升级

第三方库才是 Vue 2 升级 Vue 3 最繁琐的地方。

有些未支持 Vue 3 的库,需要自研或寻找其他的替代包,这个会阻碍升级进程。

另外,如果用到第三方 UI 库,比如 vant / element-plus 等,变动的细节很多,而我们往往也是整个项目贯穿大量使用,这时候就得每个组件去核对它的 API,结合各个库提供的破坏性改动文档,然后逐个用到的地方找出来不断修改。

比如 v-model 在这些库里变成了各式各样的 v-model:valuev-model:showv-model:open 等,细节很多,以及这些第三方库内部的样式也会发生变化,也得确认升级后的样式是否正确,尤其是使用了 :deep() 去重置样式的地方。

由于每个第三方库升级的方法各不相同,这里不逐一记录了,它们官网往往也都会有迁移指南。

使用工具辅助升级

对于大型项目,手动升级工作量比较大,可以借助 gogocode-plugin-vue 和 gogocode-element-plugin 等工具将 vue 和 element 的语法进行升级。

然后再结合手工分别对改动的内容进行 code review ,再整体启动项目,调试各个功能是否正常。