⑨ 带有空 path 的命名子路由不再添加斜线,这会影响子集的redirect ,举个例子:
⑩ 其他
- “pathToRegexpOptions” 属性被 createRouter() 中的 “sensitive” 取代
- “caseSensitive” 属性被 createRouter() 中的 “strict” 取代
- 将 “router.onReady(onSuccess, onError)” 改为 “isReady().then(onSuccess).catch(onError)” 的写法
- 将 “scrollBehavior” 中返回对象的 “x” 改为 “left”,“y” 改为 “top”
- 忽略 mixins 中的导航守卫
- 删除 “fallback” 属性,因为现在vue支持的浏览器都支持history模式
- 删除 “router.match”,合并到 “router.resolve” 中
- 删除 “router.getMatchedComponents()”
- 删除 “router.app”
- 删除路由地址中的 “parent” 属性
- 所有的导航现在都是异步的
- 取消了path-to-regexp,所以不再支持未命名的参数
- 跳转或解析不存在的命名路由或缺少params参数会报错(以前是会导航到'/')
① 全局搜索 “element-ui”,替换插件,改造如下
② 主题文件路径更换
将“~element-ui/packages/theme-chalk/src/index” 替换为 “~element-plus/theme-chalk/src/index”
将“element-ui/lib/theme-chalk/index.css” 替换为 “element-plus/theme-chalk/index.css”
③ 所有标签的size属性的值从“medium / small / mini”变更为“large / default /small”
全局搜索“size="medium"”,替换为“size="large"”
全局搜索“size="small"”,替换为“size="default"”
全局搜索“size="mini"”,替换为“size="small"”
④ <el-button>移除了“type=”text””,想维持vue2的样式,可用link属性代替
全局搜索“type="text"”,依次将<el-button>上的它替换为“type="primary" link”
不要将例如<input type=”text”>这样的改跑了
⑤ icon图标调整
element-ui是通过类名使用,如对于搜索图标是class=”el-icon-search”
而element-plus是当做组件使用,如对于搜索图标是<el-icon><Search/></el-icon>
使用之前,需要下载依赖
分支目录下命令行输入“npm install @element-plus/icons-vue”
然后全局引入,配置如下:
全局搜索“el-icon”,然后根据使用方法做出相应调整,举例如下:
- 对于loading里的spinner参数,如非必要,建议删除
因为(截止到目前)官网说使用类名,但类名已经废了,所以没找到改法
- 对于通过class使用的,改成组件的形式,具体名称对比两者官网
大概率是el-icon-后面的名称的大驼峰写法
原有属性请放到<el-icon>中,icon组件会渲染成<svg>标签
项目中有可能针对“el-icon-xxx”类名设置了样式,所以建议保留原类名
- 对于<el-input>、<el-button>上的做如下修改
⑥ <el-row>的type属性删除(element-plus使用flex布局,不用专门设置)
全局搜索“<el-row”或“type=”flex””
⑦ Date Picker / Time Picker / DateTime Picker 日期时间选择器改动
- “first-day-of-week”属性删除(官方建议用dayjs里的方法代替,具体请自查)
- “picker-options”属性删除,新增属性shortcuts、disabled-date、cell-class-name
⑧ 名称改动
全局搜索“open-delay”,替换成“show-after”
全局搜索“close-delay”,替换成“hide-after”
全局搜索“ElSubmenu”,替换成“ElSubMenu”
全局搜索“el-submenu”,替换成“el-sub-menu”
⑨ 对话框改动
全局搜索“<el-dialog”,
将它上面的“:visible.sync”改写成“v-model”,
将它上面的“:visible”改写成“:model-value”
⑩ 表单校验的调整(主要针对required)
如果表单配置了rules或required(值为null也算),就一定要有prop
除非将<el-form-item>内表单组件的validate-event属性设为false,单独关闭校验
至于为什么说required值为null也算,我们看下element-plus的源码
因为void 0 === undefined ,所以,
可以看到,当required的值不为这两个时,会赋值成false放进rules里
全局搜索“required”
首先将<FormItem>这种公共组件内部的required默认值定义为undefined或void 0
因为required: Boolean这种写法,不传值进来的话,默认值是false
然后找出所有<el-form-item>或<FormItem>标签上用了required但没有prop的地方
也就是没有prop说明没有校验的需求,仅为了显示 *
对于这种情况,这里选择将required删了,添加自定义类名,自己实现 *
这里说的异步组件,不包括vue-router的懒加载,不用改它们
用了异步组件写法的,先看下是否真的有必要作为异步组件使用,如果只是为了直接写在components里方便,建议改成普通组件写法
举个例子,使用模块联邦的远程模块需异步加载,
但如果是在vue.config.js文件中用“remotes”配置的,那么它本就是异步加载,
使用时,像普通组件一样使用就行,
没用“remotes”选项配置的,才需要自己写异步加载
如下图所示,该项目使用了“remotes”
故无需再用异步引入,修改如下:
对于真的使用异步组件的,则需包裹“defineAsyncComponent”方法,如果使用了带选项的异步组件,选项里的component改名为loader
参考代码:
$attrs现在也包含了class和style,$listeners移除,事件监听器变成$attrs的一部分
片段允许组件有多个根节点,但是需要显示的定义v-bind="$attrs"
首先全局搜索“$listeners”,
有v-on="$listeners" 的删除,有this.$listeners 的改写成this.$attrs.onXxxx
然后全局搜索“inheritAttrs”,看下有没有inheritAttrs: false
有则表示该组件的根元素不会继承$attrs,需要显示绑定,如果绑定在子元素上,
那么看一下使用该组件时,组件标签上是否定义了class和style,
在vue2它们是落在根节点上的,而在vue3会落在绑定了$attrs的那个元素上,
所以有的话请改造,确保样式等不会受到影响
最后全局搜索“v-bind="$attrs"”
如果它写在根节点,且只有一个根节点,且又无inheritAttrs: false的设置,
则可以删除,因为默认就在根节点,
如果不在根节点上,则看下有没有受到class和style的影响
$set、$delete、$children、$on、$off、$once
全局搜索它们,该删删 ,该改改
有用$children的话可以用$refs改造取代
$on、$off废弃的话Bus也就废了,有用到的话请用别的通信方式替代
Vue3用proxy代替Object.defineProperty,所以不再需要$set,请改为普通赋值写法
也可以通过自定义的全局属性重写这些方法实现原有的效果,就不用挨个修改了
顺带提一嘴.prop修饰符也移除了,用了的自行搜索解决方法
Vue3中is的渲染替换效果只在<component>标签上有用,
其他标签上的需要从“is=’xxx’”改成“is=’vue:xxx’”,否则is会被当成一个普通属性(即自定义内置元素)
全局搜索“is=”,如果有写在其他标签上的,请按上述方式改造
data现在只接收函数,并且mixins、extends的data现在变成浅合并
官方建议用组合式API代替mixins、extends
全局搜“mixins”和“extends”,看是否有data选项,有的话分析浅合并带来的改变并调整
Vue3为了遵循大括号内只是js的原则,删除了过滤器,所以需要用方法或计算属性替换
为减少工作量,建议用方法替换
首先全局搜索“Vue.filter”,如果使用了全局过滤器,官方推荐通过全局属性来改造
这里我们定义一个全局属性$filters,里面存放原本的全局过滤器
使用的时候,通过$filters调用里面的过滤器方法即可
参考代码:
然后全局搜索“ | ”(注意前后都有空格),定位到使用了过滤器的地方
万一有哪处没这样写,搜索时漏掉了,就以后run时报错了再改吧
文件内依次搜索过滤器名称
如果该过滤器在filters选项里定义了,说明它是局部过滤器,只需改成方法调用
否则为全局过滤器,方法前面要加上之前定义的全局属性$filters,才能调用的到
然后再将filters选项中的局部过滤器移动到methods中,并删掉filters选项
最后全局搜索“filters:”,删除filters选项
可能存在使用了filters选项但是没内容或者未使用的情况
render() 的作用是渲染,h() 的作用是创建vnodes,h函数现在是全局导入
vue2中是作为参数,且全名是createElement
vue3中由于VNode是上下文无关的,不能再用字符串隐式查找注册的组件
所以需要使用resolveComponent方法进行包裹
注意这里说的是参数为字符串的情况
如果h的第一个传参接收的是字符串,例如vue2的写法为“render: h => h(‘XXX’)”
那么就需要引入resolveComponent方法,改成“render: () => h(resolveComponent(‘XXX’))”
截图示例中h的第一个参数是对象,所以无需使用resolveComponent
首先全局搜索“render”,找到使用渲染函数的地方,引入h方法,然后改造
全局搜索“$createElement”,有的话,两种改法
- 第一种,引入h函数,替换“this.$createElement”
- 第二种,自定义“this.$createElement”,其余地方不变
推荐这种,改起来快,且能适配到某些插件
functional移除
Vue3建议使用有状态的组件,因为函数组件的优势已经可以忽略不不计
函数组件现在只能由接收props和context(slots、attrs、emit)的普通函数创建
全局搜索“functional”,看看有没有functional: true 或 <template functional>
下图为使用functional: true的改造示例,<template functional>的很少用,不做示范
如果在v-if、v-else、v-else-if上使用了key,则每个分支的key必须唯一
如果在<template>标签上使用了v-for,
在vue2中,<template>不能有key,解决方法是在其子节点上设置key
但是在vue3中,key应该被写在使用了v-for的这个<template>上
全局搜“<template”,看是否有在该标签上使用v-for的
有的话参考下图调整
keyCode废弃,不再支持使用数字 (即键码) 作为 v-on 的修饰符
全局搜索“@keyup”或“v-on:keyup”,有的话请查看官网自行改造
Vue2中propsData用于在创建vue实例时传入prop,vue3移除了它,可用createApp的第二个参数代替
全局搜索“propsData”,有的话请自行改造,参考如下:
全局搜索“v-enter”,有的话替换为“v-enter-from”
全局搜索“v-leave”,有的话替换为“v-leave-from”
当使用 <transition> 作为根结点的组件从外部被切换时将不再触发过渡效果
<transition-group> 不再默认渲染根元素,但仍然可以用 tag attribute 创建根元素
全局搜索“<transition”,有的话请查看官网自行改造
Vue3中v-bind 的绑定顺序会影响渲染结果
全局搜索“v-bind="{”,如果有,请参照下图修改
beforeDestroy 和 destroyed 已经分别被重命名为 beforeUnmount 和 unmounted
全局搜索“beforeDestroy”,替换为“beforeUnmount”
全局搜索“destroyed”,替换为“unmounted”
全局搜索“hook:”,替换成“vnode-”
默认prop从“value”变成“modelValue”
默认event从“input”变成“update:modelValue”
.sync修饰符移除
model选项移除
同一个组件可以有多个v-model绑定
可以自定义v-model修饰符
【使用默认v-model的写法】
- vue2 中
- vue3 中
【使用v-model搭配model选项的写法】
- vue2 中
- vue3 中
【使用.sync的写法】
- vue2 中
- vue3 中
先明确一点,对于v-model,我们要改造的是自定义组件(项目里自己写的)上的
首先全局搜索“$emit(‘input”和“$emit(“input”
单双引号、空格等情况要考虑到 如有,且组件内还用到了“value”这个prop,再根据组件名找到所以使用它的地方,看下是否用的默认v-model,是就改造
然后全局搜索“model: {”,找出所有使用model选项的自定义组件
再分别找出所有使用了它们的地方,确定它们用了v-model,然后改造
举例个特殊情况,如下图
可以看到,change事件监听器执行了2个方法,v-model自带的和额外定义的
两种改法,一种是维持1个监听器的效果:
另一种是变成2个监听器,原有的change事件保持,在它旁边增加新的监听器
最后全局搜索“.sync”,有的话,将“:XXX.sync”改写成“v-model:XXX”
emits用来定义子组件向其父组件触发的事件(写法类似props)
官方建议使用emits记录组件所触发的所有事件
任何未在emits记录的事件都会算入该组件的$attrs,
即作为原生事件添加到子组件的根元素(或定义了v-bind=’$attrs’ 的元素)中
也就是说,以前需要用.native实现的效果(如click事件)
现在只要不在emits里加同名事件(如click)就能实现
这里可以看下官方举的例子,便于理解:
这里有一点需要注意,
虽然官方只是建议用emits记录所有事件,不记录也会被放进$attrs作为原生事件用,
但是当自定义事件的名称与原生事件重名时,例如:$emit(‘click’)
不记录的话,事件可能会被触发两次,或者意料之外的状况,
所以,要么自定义事件命名时避开原生事件名,要么,就在emits中记录
首先全局搜索“.native”,直接点击替换,删除.native
然后全局搜索以及文件内搜索“this.$emit(”,增加emits选项,记录所有自定义事件
vue2中,$slots用来访问插槽分发的内容,$scopedSlots用来访问作用域插槽
Vue3中,移除了$scopedSlots,将插槽作为函数公开(以前是对象)
【具名插槽】
- vue2 中
- vue3 中
【作用域插槽】
- vue2 中
- vue3 中
注意,v-slot只能写在<template>中,除非是独占默认插槽(能写在组件标签上)
首先全局搜索 “$scopedSlots”,将 “$scopedSlots” 替换为 “$slots”
再全局搜索 “$slots”,将 “$slots.XXX” 替换为 “$slots.XXX()”
请分开搜索避免遗漏,因为在vue2中他们是两个东西,只不过在vue3中统一了写法
然后全局和文件内搜索 “slot=”, 依次将 “slot='XXX'” 改成 “#XXX” 或者 “v-slot:XXX”
对于非<template>标签上的slot, 先在它的外层包裹上<template>标签,然后将slot挪到<template>上
最后全局搜索“slot-scope=”,替换成“#default=”或者“v-slot:default=”
样式中使用“/deep/”、“>>> ”、“::v-deep”的会报错
全局搜索它们,然后换成“:deep()”的格式
对剩下的依赖(第1步没处理的)进行升级或替换,适配vue3,
注意需要调整的肯定是插件内部有使用到vue相关功能的, 如果有依赖只能用vue2版本的话,请记录下来,后续只能继续使用迁移构建版本
举个例子,如果使用了“@riophae/vue-treeselect”插件
分支目录下命令行输入“$ npm uninstall @riophae/vue-treeselect”
然后输入“npm install --save vue3-treeselect”
全局搜索“@riophae/vue-treeselect”
先将“@riophae/vue-treeselect/dist/vue-treeselect.css”
修改为“vue3-treeselect/dist/vue3-treeselect.css”
再将“@riophae/vue-treeselect”替换为“vue3-treeselect”
首先去除Vue的引入,然后改造singleSpaVue()的传参,
router和store已经通过use引入,所以appOptions里不用再写
将“Vue”换成“createApp”,插件会自己创建一个vue实例,
然后将实例作为参数调用handleInstance的方法(有的话),之后会将实例挂载
请在appOptions里传入el,否则插件会自己在body创一个容器,
这样的话,不管将实例挂载在哪,都会多出一个容器,影响页面展示,详情请看源码
现在我们有两个app实例了(自己创的用于单独运行项目的,以及微前端里插件创的),
我们将之前定义的一堆东西封装成一个方法,然后让两个实例都调用它
顺带一说,vue-router v4.x中的router.history已经移除了,所以这里删掉它, 可以分别打印一下v3.x和v4.x的router对比一下,也可参考官网深入解读
具体改动可参考下图:
以下改动项目里会用到的概率低,可自行检查,也可作为错误排查的参考:
- v-for上有ref的,ref不再自动创建
- props默认值不能再访问this
- v-if和v-for优先级变动,在vue2中v-for高,vue3中v-if高
- attribute 强制行为改动(值为false的处理方式有改动,具体官网自查)
- 挂载有template的应用时,从vue2的替换元素变成vue3的作为子元素插入
- 没有特殊指令的 <template> 现在会被渲染为原生元素
到这里,常规的迁移工作就完成了, 接下来请尝试 lint 一下或直接运行项目, 如果还有报错或警告,请逐一检查,需要修复的就修复(第32步有举例可参考), 修复完成后,如果项目中没有必须依赖vue2的地方, 就可以去掉迁移构建版本,切换成vue3版本,否则只能继续使用迁移构建版本, 之后,请对系统功能做测试验证,测试所有组件及交互, 可能还会有错误或警告,再做修复
确定项目没有依赖vue2的地方后,我们开始尝试去掉迁移构建版本
建议先注释掉,后续验证完系统功能,确定vue3迁移成功后,再删除
① 命令行可能会发现报错Unexpected mutation of "XXX" prop
这是eslint对单向数据流的检测,子组件直接修改了prop就会报这个错
如果是个新项目,那么以它为约束进行开发是很好的, 但是如果现有的项目已经有写成这样不规范的且运行正常,就不要轻易改动了, 代价大且容易产生新的风险
这里我们在.eslintrc.js文件中配置“'vue/no-mutating-props': 'off'”关闭这个检测
② 无关的非props属性传递给组件带来的警告
如果往组件传递了个未被定义属性(如下图的visible),且它又不是$attrs里带的(如title),
就会报这样的警告,大概率是代码有误
比如下图为<el-dialog>中写成“v-model:visible”所报的错,解决办法是写作“v-model”
③ 无关的非emits事件监听器传递给组件带来的警告
如果往组件传递了个未被定义属性(如下图的beforClose),且它又不是$attrs里带的(如input),
就会报这样的错,大概率是代码有误
比如下图,
“@befor-close”是错误写法,正确用法是“:befor-close”,
所以解决方法是删掉<el-dialog>上的“@befor-close”
④ 使用了废弃属性带来的警告
查看“vue3-treeselect”源码后发现,它使用了functional(vue3已移除),
完全切换成vue3版本后就不会有这个警告了,所以忽略这个警告
⑤ 解析不了标签带来的警告
不影响使用,忽略这个警告
⑥ attribute 强制行为改动带来的警告
如下图所示,可以看到“aria-current”这个属性(li标签上的无障碍属性),
再对比下vue3中对于attribute 强制行为的改动,
也就是说,对于“aria-current”,element-plus是希望,当它的值为false时,
输出为“aria-current=‘false’”,而不是移除
完全切换成vue3版本后就不会有这个警告了,所以忽略这个警告
⑦ 使用未定义的实例属性带来的警告(大概率是代码有误)
下图的例子是因为vue2中的“this.$createElement”也就是h函数,
在vue3中变成了通过import使用,“this.$createElement”也删除了
改法在第15点说过了,这里是插件的问题(用了但没完全用),建议用第二种改法
别忘了学习Vue3的组合式API
官方推荐vue3的项目使用vite代替vuecli,
但是考虑到迁移成本、兼容性以及社区生态等因素,短期内还是推荐继续使用vuecli
Vuecli迁移vite教程,感兴趣的可以了解一下
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ri-ji/14082.html