随着 vue3 的发布和越来越多项目的使用,之前使用 vue2 的项目也不能落下。虽然 vue3 具有一定的向下兼容性,但还是有一些破坏性的改动,并且 vue3 相较于 vue2 在运行效率和开发体验上有较好的提升。vue3 比较明显的一个变化就是添加了 setup(){} 函数,使得业务逻辑的复用性更强,代码组织更具有条理性。即使是这样,小改动还是很多的。

   在大佬们的指导下,整理了目前 vue2 升级为 vue3 的不兼容变更项。如有遗漏,望大家不吝指出。

升级前

在正式升级前,可以提前完成兼容性的改动。

模版

  1. 排查同时使用 v-ifv-for 的元素,避免在同一个元素上同时使用,可以通过 computed 方式过滤出可见元素的列表;
  2. 排查元素 v-bind 的前后使用,确保 v-bind 先定义,再定义各个属性;
  3. 排查 v-for 中使用 ref 的地方,将 ref 绑定为一个函数;

渲染函数

  1. 排查所有 this.$scopedSlots 更改为 this.$slots
  2. 全局搜索使用 slot-scope 的地方改为 v-slot ;

其他改动

  1. 排查所有的组件中的 data 类型,确保 data 必须是返回 objectfunction
  2. 排查所有使用 mixinextend 的组件,确保 data 中的属性不重复,或者都为顶级属性;
  3. 排查所有的 watch 的参数,如果监听参数为数组,需要设置 deep: true

移除 API

  1. 排查使用数字 (即键码) 作为 v-on 的修饰符,更改为别名的方式 参照。示例:
vue2
v-on:keyup.112

vue3
v-on:keyup.delete
  1. 移除 config.keyCodes
  2. 排查使用 keyCode ,建议转换为对应的 kebab-cased (短横线) 命名 参照
  3. 全局搜索 filters ,更改为使用 computedfunction 代替 filters ;对于使用较多场景的 filters 可以考虑使用全局的 filters 示例:
// main.js
const app = createApp(App)

app.config.globalProperties.$filters = {
  currencyUSD(value) {
    return '$' + value
  }
}

// vue组件
<template>
  <h1>Bank Account Balance</h1>
  <p>{{ $filters.currencyUSD(accountBalance) }}</p>
</template>
  1. 全局搜索 inline-template ,移除 inline-template 标识,如果必须使用可用 <script> 或者默认 Slot
  2. 全局搜索 $children ,移除 $children 实例,如果需要访问子组件实例可用 $refs
  3. 全局搜索 $destroy ,移除 $destroy 实例,不应该手动管理单个 Vue 组件的生命周期;

升级中

全局

  1. 排查 vue 实例创建方式,将 new Vue() 更改为 createApp
2.x Global API3.x Instance API (app)
Vue.configapp.config
Vue.config.productionTipremoved ( see link )
Vue.config.ignoredElementsapp.config.isCustomElement ( see link )
Vue.componentapp.component
Vue.directiveapp.directive
Vue.mixinapp.mixin
Vue.useapp.use ( see link )
  1. 排查使用的全局 API 更改为 ES 模块;
    • Vue.nextTick
    • Vue.observable(更改为Vue.reactive)
    • Vue.version
    • Vue.h
    • Vue.compile(仅完整版本)
    • Vue.set(仅在兼容版本中)
    • Vue.delete(仅在兼容版本中)

模版

  1. 排查没有修饰符的 v-model,分别将 propevent 命名更改为 modelValueupdate:modelValue
  2. 全局搜索.native,移除 v-on.native 修饰符,将需要进行参数校验的 emit 写入 emits 中;
  3. 移除没有指令的 <template>,vue3 支持多个节点返回;
  4. 全局搜索 .sync,将元素中 v-model.sync 更改为 v-model:value

组件

  1. 排查函数式组件,移除配置中 { functional: true } 和模板中 <template functional>functional
  2. 排查单文件组件,props 重命名为 $propsattrs 重命名为 $attrs
  3. 排查路由和异步组件,异步组件通过 defineAsyncComponent 方法创建;
  4. 排查 defineAsyncComponentdefineAsyncComponentcomponent 选项需要改成 loader ,同时 loader 函数移除了 resolvereject 参数,必须手动返回 Promise

渲染函数

  1. 排查所有使用 render 的组件,更改 VNode domProps 结构 参照
  2. 全局搜索 $listeners ,删除所有的 $listeners
  3. 排查所有设置了 { inheritAttrs: false } 的组件,确保升级后的样式是否正确。如果之前依赖 classstyle 。vue3 中 $attrs 包含了所有的 attribute 包括 classstyle ,这些 attribute vue2 版本中 classstyle 则不会;
  4. 全局搜索 v-enter 替换为 v-enter-from ,类名重命名;
  5. 全局搜索 v-leave 替换为 v-leave-from ,类名重命名;
  6. 排查 watch$watchwatch 不再支持点分隔字符串路径。如 user.userName 可以将监听的参数更改为 computed
  7. 排查使用到 outerHTML 的组件,在 vue2 中,应用根容器的 outerHTML 将替换为根组件模板 (如果根组件没有模板/渲染选项,则最终编译为模板)。vue3 现在使用应用程序容器的 innerHTML ,容器本身不再被视为模板的一部分;

生命周期

vue2vue3vue3 setup
beforeCreatebeforeCreatesetup() 内部
createdcreatedsetup() 内部
beforeMountbeforeMountonBeforeMount
mountedmountedonMounted
beforeUpdatebeforeUpdateonBeforeUpdate
updatedupdatedonUpdated
beforeDestroybeforeUnmountonBeforeUnmount
destroyedunmountedonUnmounted
errorCapturederrorCapturedonErrorCaptured
renderTrackedonRenderTracked
renderTriggeredonRenderTriggered

其他

  1. 排查全部 propdefault ,确保不含 this ,如有需要可以用 inject 来访问注入的 property
  2. 查找自定义指令(通常在 directive 文件夹下),修改生命周期如下:
vue2vue3
bindbeforeMount
insertedmounted
beforeUpdate
update移除(改用 updated )
componentUpdatedupdated
beforeUnmount
unbindunmounted

升级后

vue3 官网

  1. 逐步移除 option API 替换为 composition API
  2. 对于 JS 的开发可以考虑迁移为 TS

相关配套设施

elementUI

目前还不支持 vue3;

vuex

已支持 vue3 ,目前改动不大,任务紧急度较低;

vue-router

创建实例

new VueRouter 更改为 VueRouter.createRouter

路由模式

查找路由下的 { mode: 'hash' } ,更改为 { history: VueRouter.createWebHashHistory() }

挂载根实例

通过 { app.use } 的方式挂载路由

使用

option API 中依旧可以通过 this.$route 读取到当前路由信息,this.$router 读取到路由表信息;
composition API 中需要使用 useRouteruseRoute 函数。例如:

const router = useRouter();
const route = useRoute();

break changes

移除 tag 新增 v-slot 例如:

<router-link to="/about"
  custom
  v-slot="{ href, route, navigate, isActive, isExactActive }"
>
  <NavLink :active="isActive" :href="href" @click="navigate">
    {{ route.fullPath }}
  </NavLink>
</router-link>

v-slot 的对象包含下面几个属性:

  1. href:解析后的 URL。将会作为一个 a 元素的 href attribute
  2. route:解析后的规范化的地址;
  3. navigate:触发导航的函数。会在必要时自动阻止事件,和 router-link 同理;
  4. isActive:如果需要应用激活的 class 则为 true。允许应用一个任意的 class
  5. isExactActive:如果需要应用精确激活的 class 则为 true。允许应用一个任意的 class

使用 useLinkv-slot API 相同,返回的都是相同的属性。

测试

项目构建成功,通过页面切换,验证功能是否按照预期显示。

Logo

前往低代码交流专区

更多推荐