vue2 to vue3 升级排雷

11,010 阅读5分钟

为了拥抱变化,跟上时代的潮流,将 vue2 项目升级至 vue3 ,在升级过程中,发现很多坑。也许问题很简单,但是当思维陷入误区的时候,又会给我们造成很大的困扰,因此将这次升级中遇到的坑总结整理出来,希望可以为有同样需求的小伙伴提供一定的帮助。

话不多说,下面进入正题

VUE2 to VUE3 有哪些变化

关于这部分相信网上有很多同学已经整理过,而且整理的比我好很多,因此我也就不再赘述,贴两个我看过觉得很不错的地址,大家可以自行查看

Vue 官方文档

# Vue3.0 新特性以及使用经验总结

接下来就是我遇到的坑了,当排查完成后,有种像癞蛤蟆爬脚面,不咬人它膈应人的感觉……

Antd 3

相信很多人跟我一样,在升级 vue2 的同时,会将内部的用到的包进行升级。我这次是将 ant-design-vue 从 1 升到 3 。

中间遇到了一些问题,我最开始以为是 vue3 导致的,实际上是 ant 升级导致的。

1.antd3 移除了 formModel 组件

在迁移的过程中,你会发现,原项目使用的 a-form-model 无法识别,原因就是 ant3 移除了这个组件,全部使用 a-form 。绑定通过 v-model 的形式。

2.antd3 移除了 Icon 组件

在迁移过程中,原项目使用的 a-icon 无法识别,原因是 ant3 中的 Icon 调用方法有所调整, ant-design-vue 中已经没有导出 Icon 组件了。

//新的调用方法
<template>
<message-outlined :style="{fontSize: '16px', color: '#08c'}" /> </template>
<script> 
import { MessageOutlined } from '@ant-design/icons-vue';
import { defineComponent } from 'vue'; export default defineComponent({ 
components: { MessageOutlined, }, 
}); 
</script>

3.样式问题

升级中,最避免不了的问题,当然就是样式错乱的问题。 经过排查发现, ant3 中的 ant-modal-body ,ant-drawer-body 默认存在 padding ,而在之前的版本中,这两个是没有 padding 属性的,所以样式需要重写

4.prop属性

ant3 的 form 中原本的 prop 属性已经废弃,现在变成了 name 属性。 另外,如果想停止数据收集,可以通过以下方式

//组件库提供了一个 `a-form-item-rest` 组件,它会阻止数据的收集,
你可以将不需要收集校验的表单项放到这个组件中即可,不会产生额外的 dom 节点。

<a-form-item>
    <a-input name="a">
    </a-input> 
    <a-form-item-rest>
        <a-input name="b">
        </a-input>
    </a-form-item-rest> 
</a-form-item>

PS: 补充一点, a-form-item-rest 会有一个副作用,就是设置 validate 的时候,不会跟随 trigger 触发 校验方法

vue-i18n 升级问题

相信很多同学在使用 vue2 的时候,已经习惯了 template 中直接使用 ¥t , js 中使用 this.$t 的方式调用国际化语言

但是当我们升级到 vue3 后,这种方法已经不再适用,在 template 中使用方式差不多,但是在 js 中使用的方式由很大的变化。

vue3 中如果想在 js 中使用 i18n ,需要通过 vue-i18n 提供的 hook : useI18n 来获取 t 对象, 之后再通过 t 调用

import { useI18n } from 'vue-i18n'

const { t } = useI18n()

const label = t('test')

vueI18n 官方文档

Swiper 升级问题

在项目中使用了轮播图,原来的轮播图使用只需要将 swiper 注入就可以了,但是升级 vue3 后再想使用轮播图就没有那么简单了,你需要按如下方式写才能正常调用

import SwiperCore, { Navigation, Pagination, Scrollbar, A11y, Autoplay } from 'swiper';
import { Swiper, SwiperSlide } from 'swiper/vue';

// 使用了什么属性,需要先在这里引入,比如 Mousewheel
SwiperCore.use([Navigation, Pagination, Scrollbar, A11y, Autoplay, Mousewheel]);

export default defineComponent({
    components:{Swiper, SwiperSlide}
})

注意 新版的 swiper 的属性无法通过 swiperOptions 进行配置,都需要展开配置才能生效!

# 如何在vue中使用swiper6,解决Mousewheel失效

# vue项目中使用swiper遇到的坑

slideTo

在我升级的过程,还会发现,原来使用 ref 绑定 swiper ,然后直接调用 slideTo 就可以了,但是在升级 vue3 后 ,会报错 slideTo is not a funciton

其实找了很久也没找到到底应该怎么绑定,后来使用了一个办法,确实解决了问题。就是在 swiper 的组件中 ,通过 onSwiper 触发绑定赋值,而不是通过 ref, 这样我就将 swiper 的实例赋值到 vue 的 date 中,后面就可以直接调用了

vue-qrcode 不支持 vue3

使用 qrcode.vue

vue 生成二维码插件 vue-qrcode

杂七杂八问题

  • Ant Design Vue 输入框绑定不上值解决方案

  • vue3 中事件分发分为 context 的 emit 和 eventBus 的 emit ,分别是父子传播和垮多个传播的区别

  • antd3 中的 validate 不存在 callback 回调了,所以新的写法改成了这样

const valid = await (ruleForm.value as any)?.validate()
  • 使用 ref 或者 computed 在 js 中使用,后面需要添加 .value, return 到 模板后无需加入 .value

  • vue3 去掉了 .sync 修饰符,如果想使用的话, 通过 v-modal:变量名 来绑定

  • vue3 Uncaught SyntaxError: Unexpected token '<' 这是因为输入不存在的路由地址

//在项目中,我的router这么配置的,会报上面那个错误

const  router = [
{

path: "/url/:id",

name: "url",

component: LoginLayout,

},
]

//解决办法 vue.config.js 里

module.exports = {
// publicPath:  "./",  // 改成下面这样
  publicPath: process.env.NODE_ENV === "production" ? "./" : "/"
};

总结

我自己之前也是主要使用 React ,这次也算是学习 Vue 的各种写法,以上都是我在学习过程中遇到的一些问题,也许很简单,但对于不知道的人来说确实很难找到解决办法,我也是在升级过程中一点点 google 出来的解决办法,也许没有找到最正确的方式,但确实解决我面对的问题。

整理出来作为自己的总结归纳,也希望可以帮助到有需要的人~