背景

由于最近有需求需要把vue3项目的功能搬到vue2项目中,而vue3中大多数用的组件库组件,组件库又是用elment plus+vue3写的。为了防止后续搬运改写麻烦,所以决定升级旧项目。

直接用vite脚手架生成了一个新的vue3项目,引入element plus组件,并且把除了git文件夹以外得旧项目文件直接复制到新项目,然后解决不兼容问题。

以下是在升级中遇到的一些问题总结

一、插件

jsx需要引入@vitejs/plugin-vue-jsx

之前得项目用了vue2中得render方法,直接return了对应得模板,升级到vue3后,需要引入@vitejs/plugin-vue-jsx插件,并在vite中配置

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'

export default defineConfig({
  plugins: [
    vue(),
    vueJsx()]
    })

因为vue2项目都没有指定jsx类型,所以需要在使用了jsx的组件中得js指定对应得lang=jsx

二、 element-plus

使用自动引入插件后自定义主题色不生效

官网上有提供自定义主题色功能,但是跟着配置后不生效,查了一下,跟vite中的配置有关,使用自动导入插件时,记得配置

ElementPlusResolver({
          importStyle: 'sass',
        })

详情配置如下

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import path from 'path'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import { createStyleImportPlugin } from 'vite-plugin-style-import'
import VueSetuoExtend from 'vite-plugin-vue-setup-extend'

export default defineConfig({
plugins:[
vue(), vueJsx(),VueSetuoExtend(),
AutoImport({
      // Auto import functions from Vue, e.g. ref, reactive, toRef...
      // 自动导入 Vue 相关函数,如:ref, reactive, toRef 等
      imports: ['vue','vue-router','@vueuse/core'],
      // Auto import functions from Element Plus, e.g. ElMessage, ElMessageBox... (with style)
      // 自动导入 Element Plus 相关函数,如:ElMessage, ElMessageBox... (带样式)
      resolvers: [
        SpectrumResolver(),
        ElementPlusResolver({
          importStyle: 'sass'
        }),
      ],
      dirs: ['src/api/**', 'src/hooks/*'],
      dts: true,
    }),

    Components({
      dirs: ['src/components'],
      resolvers: [
        // Auto register Element Plus components
        // 自动导入 Element Plus 组件
        ElementPlusResolver({
          importStyle: 'sass',
        })
      ],
      include: [
        /\.[tj]sx?$/, // .ts, .tsx, .js, .jsx
        /\.vue$/, /\.vue\?vue/, // .vue
      ],
      dts: true,
    }),
    // unplugin-vue-components不支持jsx,使用jsx时仍然需要import组件,用于import组件时自动引入样式
    createStyleImportPlugin({
      libs: [
        {
          libraryName: 'element-plus',
          ensureStyleFile: true,
          esModule: true,
          resolveStyle: (name) => `element-plus/es/components/${name.slice(3)}/style/index.mjs`,
        },
      ],
    }),
],
css: {
    preprocessorOptions: {
      scss: {
        additionalData: ` @use "@/styles/element/index.scss" as *;`,
        api: 'modern-compiler' // 如果您的终端提示 legacy JS API Deprecation Warning, 您可以配置以下代码在 vite.config.ts 中
      },
    },
  },
})

其中css的additionData配置的路径,就是跟着你要设置的主题色

src/styles/elment/index.scss

@forward 'element-plus/theme-chalk/src/common/var.scss' with (
  $colors: (
    'primary': (
      'base': #0E42B9,
    ),
  ),
);

编译时$ref找不到

从element ui升级到element plus时,有出现

$colors: () !default;
$colors: map.deep-merge(
  (
    'white': #ffffff,
报$ref找不到的错误,sass未能兼容

解决方案,将element plus升到最新版本(最近更新了新版本,似乎解决了问题)

keep-alive

升级vue3后,对应的router-vue也要升级到第四版本,其中router-view对keep-alive的写法变了,正确写法如下

<router-view v-slot="{ Component }">
   <transition name="fade-transform" mode="out-in">
      <keep-alive :exclude="noAlivePage" :include="keepAliveList">
          <component :is="Component" :key="key" />
      </keep-alive>
   </transition>
</router-view>

其中include内的才会有对应的缓存,而想要缓存上组件,必须每个组件都命名,并存入对应的keepAliveList。因为是vue2升上到vue3,使用插件vite-plugin-vue-setup-extend,并在每个页面的setup中给name赋值即可

<script setup lang="tsx" name="componentName">

自动导入

用了自动导入插件,发现自定义的文件夹方法,在导入文件内找不到,即没有自动导入
解决方案,升级unplugin-auto-import,unplugin-vue-components

element ui 与element plus 的组件差异

以下简称element ui为ui,element plus为plus

el-select

因为element plus改了flex布局,适应父组件100%,如果没有设置el-select,宽度会很小。

el-dialog

ui中控制dialog打开时visible,plus是以v-model控制

el-date-picker

plus中只能以v-model赋值和监听

el-message

如果vue2项目中在js中有用到this.$message,则需要全局定义一个message变量,绑定ElMessage

el-loading

plus中需要主动导入loading后,组件上使用v-loading才生效

el-radio

plus中radio的值不再是label获取,变成了value获取

三、vue2与vue3写法

vue3与vue2大多数是可以兼容的,但是有部分写法不同

props

vue3中不允许更改props传入的值,需得更改以前的错误写法,否则不能正确赋值

$set

vue3中废弃了$set

sync同步

vue3中使用v-model,sync不生效

filter

vue3中废弃了filter

环境变量获取

此次升级了用的vite,所以获取对应的环境变量不再是process.env,变为import.meta.env

大体上是这些问题,小的问题可能还有以前数据处理没有规划好,比如数据很大的接口没有分页导致页面卡顿,需要优化。样式上::v-deep废弃了,需要改为:deep()

遇到大大小小挺多错误的,大多数都是可以批量更改,不少问题也是定位不到位,所以比较耗费时间。也可能有没记全的问题,不管咋说,项目看起来是升级结束了,撒花!!!

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐