vue3 升级实战笔记

2023-04-11  本文已影响0人  VioletJack

最近要将公司项目的移动端进行 vue3 的升级工作,就顺便记录下升级过程。

项目迁移的思路

我的想法是最小改动原则。

项目创建

由于改动太大,我并没有在原项目上进行升级,而是使用最新的 vue 模板来新建项目,然后逐步迁移代码。

$ npm init vue@latest
✔ Project name: … app-v3
✔ Add TypeScript? … No
✔ Add JSX Support? … Yes
✔ Add Vue Router for Single Page Application development? … Yes
✔ Add Pinia for state management? … No
✔ Add Vitest for Unit testing? … No
✔ Add Cypress for both Unit and End-to-End testing? … No
✔ Add ESLint for code quality? … Yes
✔ Add Prettier for code formatting? … Yes

Scaffolding project in ./<your-project-name>...
Done.

这里我并没有用 TS 和 Pinia 库,主要还是因为用了这两个库,迁移成本会大大增加,需要改动的代码会多很多。以后再慢慢升级吧。

安装依赖

项目也运行了一两年了,用到的依赖必然是不少的。逐个进行安装。这里需要将库分为两类:

vue 相关库

这类库要么是基于 vue3 来重写的,要么就是针对 vue3 的新特性而设计实现的。这类库就需要从 vue2 升级到 vue3。我项目中用到的库有:

{
  "element-plus": "^2.3.2",
  "vant": "^4.1.2",
  "vue": "^3.2.47",
  "vue-router": "4",
  "vuex": "^4.0.2",
  "vxe-table": "^4.3.11"
}

对于这类库,或多或少会和老版本的 API 有一些出入,所幸一般优秀第三方库的文档都会提供 vue3 的迁移指南。

其他工具库

这类库基本上是可以直接从 package.json 里面复制过来用的。后续执行 npm install 安装即可。

{
  "@antv/g2plot": "^2.4.29",
  "axios": "^1.3.4",
  "dayjs": "^1.11.7",
  "lodash": "^4.17.21",
  "numeral": "^2.0.6",
  "query-string": "^8.1.0",
  "vconsole": "^3.15.0",
  "xe-utils": "^3.5.7"
}

dev 开发库

另外,在开发中还会用到一些开发工具库,如 CSS 预处理器

> npm add -D sass

这类开发相关库的用法参考 vite 官方指引(感觉它的文档和 vue-cli 还是有些类似的)。

注册依赖库

这些其实就很简单,按照各自官方文档配置即可。一般都是 app.use(lib, { ...options }) 的写法。

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import Vant from 'vant'
import 'vant/lib/index.css'
import VXETable from 'vxe-table'
import 'vxe-table/lib/style.css'

const app = createApp(App)

app.use(router)
app.use(store)
app.use(ElementPlus)
app.use(Vant)
app.use(VXETable)

app.mount('#app')

接口代理

代理是开发阶段前后端联调的关键,比如第一时间安排上。

// vite.config.js
export default defineConfig({
  ...
  server: {
    port: 7001,
    proxy: {
      '/api': 'http://101.44.97.172',
    },
  },
})

代码如何迁移

由于并没有使用 TypeScript 和 Pinia,所以完全可以一股脑将项目全部移到新项目上。再对改动逐个调整。

处理 devtools 不显示的问题

在跑 vue3 项目的时候,发现它并没有将 vue-devtools 调试工具开起来,于是就去官网查询。

https://devtools.vuejs.org/guide/faq.html#the-vue-devtools-don-t-show-up

解决方案是修改一个环境变量 __VUE_PROD_DEVTOOLS__,它默认是 false,需要改为 true 来打开。

__VUE_PROD_DEVTOOLS__ (enable/disable devtools support in production, default: false)

对于 vite 构建的项目(一般都是用的 vite),可以使用使用 define 选项.

// vite.config.js
export default defineConfig({
  ...
  define: {
    __VUE_PROD_DEVTOOLS__: true,
  },
})

vue-router

在路由方面,改动并不大(毕竟是同一个库的升级版)。下面列出了 vue2 和 vue3 的使用方式不同之处。

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

const router = new VueRouter({
  routes: [
    {
      path: '/',
      name: 'welcome',
      component: () => import('@/views/Welcome/index.vue'),
      meta: {
        title: '引导页',
        key: 'welocome',
      },
    },
  ],
})

window.vm = new Vue({
  router,
  render: (h) => h(App),
}).$mount('#app')
import { createApp } from 'vue'
import { createRouter, createWebHashHistory } from 'vue-router'

const router = createRouter({
  history: createWebHashHistory(),
  routes: [
    {
      path: '/',
      name: 'welcome',
      component: Welcome,
      meta: {
        title: '引导页',
        key: 'welocome',
      },
    },
  ],
})

const app = createApp(App)
app.use(router)

另外一点不同是在 JavaScript 中去 route 的方式不同。

在 vue2 中可以在 vue 实例中拿到路由信息。

const $route = window.vm.$route

而在 vue3 中我是通过如下方式取的 route 信息。

import router from '@/router'

const $route = router.currentRoute.value // currentRoute 是一个 ref() 对象

目前用到的就这些,其他改动详见 从 Vue2 迁移 | Vue Router

vuex

关于 vuex 部分,表现倒是出奇的好。代码拷贝过来后修改了安装过程,其他都能运行正常。

import { createStore } from 'vuex'

export const store = createStore({
  state() {
    return {
      count: 1,
    }
  },
})
import { createApp } from 'vue'
import { store } from './store'
import App from './App.vue'

const app = createApp(App)

app.use(store)

app.mount('#app')

这就体现出我之前所说的 vuex 比 pinia 的迁移上的好处了。

vue3 语法修改

由于采用了选项式语法来写 vue ,所以老项目的大多数 API 还是可以适用的。最需要关注变化是那些非兼容性改变 | Vue 3 迁移指南。下面列举一些我遇到的问题。

export default {
  props: {
    value: String,
  },
  emits: ['update:value'],
  methods: {
    handleClick() {
      const index = this.options.findIndex(
        (option) => option.value === this.value,
      )
      if (index === this.options.length - 1) {
        this.$emit('update:value', this.options[0].value)
      } else {
        this.$emit('update:value', this.options[index + 1].value)
      }
    },
  },
}

vant 组件库的变化

我的移动端项目用到了大量 vant 的组件库,所以记录了一下影响较大的改动。

具体还是可以参考 vant 的 升级指南 来进行更新。

总结

const elements = document.getElementsByClassName('vxe-table--body-wrapper')
elements.addEventListener('touchend', () => {})

// 这种结构性的元素获取最容易出问题
document.querySelector('#app > div > div:nth-child(3)')
.header-tabs {
  width: 100%;

  :deep(.van-tab) {
    font-size: 16px;
    font-family: PingFang SC;
    font-weight: 500;
    color: #282c32;
  }

  :deep(.van-tab--active) {
    font-size: 16px;
    font-family: PingFang SC;
    font-weight: bold;
    color: #f6674f;
  }

  :deep(.van-tabs__line) {
    width: 65px;
    background: #f6674f;
  }
}
上一篇 下一篇

猜你喜欢

热点阅读