之前对一个项目有兴趣,里面的前端框架使用了 Vue2,然而本地测试部署的时候,包管理器会报告大量的风险,于是就想着把它更新到 Vue3。不曾想这是遇到了 Vue 升级史上的高级别难度关卡,从基础层面就会有大量的不兼容。为了把自己的踏出来的第一步推进下去,要查阅挺多信息,然而在打开若干标签页之后,终于还是把时间又让给了其它的事情。然后,就又到了要清理标签页的时候了,为了不让先前的过程白费,尽可能在这里留下一些摘抄、记录、感想等等的痕迹。
感受 Vue3 跟 Vue2 不一样的第一个重量冲击来自于事件总线机制发生了变化。
在 Vue2 里面,各种操作的简略表达如下:
Vue.prototype.$bus=new Vue()
- 监听:
this.$bus.$on(‘方法名', (参数)=>{})
,它可以累加 - 触发:
this.$bus.$emit(‘方法名', 实参值)
- 销毁:
this.$bus.$off(‘方法名')
,谁监听谁销毁 - 注意: 由于监听可以累加,所以必须要有第 4 步的销毁
到了 Vue3 里面,通常要借助于额外 npm 的组件 tiny-emitter
或者 mitt
来通讯,网上看尤以后者居多。如果是前者,则用法基本上如,
1 2 3 4 5 6 7 8 9 10 |
import emitter from ‘tiny-emitter/instance' import {onMounted} from ‘vue' setup(){ onMounted(()=>{ emitter.on('监听的方法名', (参数)=>{回调函数}) // 监听 emitter.emit('监听的方法名', 参数) // 触发 emitter.off('监听的方法名', 参数) // 销毁 }) } |
如果是后者,则如,
1 2 3 4 5 |
import mitt from ‘mitt' bus.on('监听的方法名', (参数)=>{回调函数}) // 监听 bus.emit('监听的方法名', 参数) // 触发 bus.off('监听的方法名', 参数) // 销毁 |
举例如,首先在 main.js
注册,
1 2 3 4 5 6 7 8 9 10 11 |
import mitt from 'mitt' const $bus = {} const emitter = mitt() $bus.on = emitter.on $bus.emit = emitter.emit $bus.off = emitter.off app.config.globalProperties.$bus = $bus app.mount('#app') |
在事件接收的页面里写,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
import {getCurrentInstance, onUnmounted} from 'vue' setup() { const $bus = getCurrentInstance().appContext.config.globalProperties.$bus $bus.on('eventName', options => { // 自定义业务 }) // 清除监听 onUnmounted(() => { $bus.off('eventName') }) } |
在事件发送的页面里写,
1 2 3 4 5 6 7 8 |
import {getCurrentInstance} from 'vue setup() { const $bus = getCurrentInstance().appContext.config.globalProperties.$bus let params = {a: 123} // 自定义数据 $bus.emit('eventName', params) } |
以上为简略版的示意。参考链接如下:
– https://www.jb51.net/article/223798.htm
– https://blog.csdn.net/qq_41577134/article/details/119956038
还有更详细的一篇是《vue2 升级至 vue3 项目技术栈升级攻略》,讲述从 Vue2 到 Vue3 的基本迁移步骤。
首先是依赖层面 package.json
更新版本依赖,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
{ "name": "myApp", "version": "0.1.0", "private": true, "scripts": { "dev": "vue-cli-service serve", "build": "vue-cli-service build", "lint": "vue-cli-service lint --no-fix" }, "dependencies": { "element-plus": "^1.1.0-beta.9", "vue": "^3.2.9", "vue-router": "^4.0.11", "vuex": "^4.0.2" }, "devDependencies": { "@vue/cli-plugin-babel": "~4.5.0", "@vue/cli-plugin-eslint": "~4.5.0", "@vue/cli-plugin-router": "~4.5.0", "@vue/cli-plugin-vuex": "~4.5.0", "@vue/cli-service": "~4.5.0", "@vue/compiler-sfc": "^3.0.0", "vue-template-compiler": "^2.6.14" } } |
然后在代码层面,依次,
1)new Vue()
改写为 createApp()
。因为 vue2 使用 new Vue()
创建 vue 实例,vue3 通过 createApp()
创造实例。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// vue2 import Vue from 'vue'; new Vue({ render: h => h(App) }).$mount("#app"); // 修改为: // vue3 import { createApp } from 'vue'; import App from "./App.vue"; const app = createApp(App); app.mount('#app'); |
2) Vue.prototype
改写为 app.config.globalProperties
3)Vue.extend
废弃,如果要拓展组件要使用 extends
属性
4)Vue 全局方法改写为实例的方法
5)filter
弃用,可以通过 compute
定义函数代替;如果是全局定义的 filter
方法,可以通过定义 filter
全局常量来代替
6)event bus 废弃,可自行实现一个 event bus 封装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
class Bus { constructor() { // 收集订阅,调度中心 this.list = {}; } // 订阅 $on(name, fn) { this.list[name] = this.list[name] || []; this.list[name].push(fn); } // 发布 $emit(name, data) { if (this.list[name]) { this.list[name].forEach((fn) => { fn(data); }); } } // 取消订阅 $off(name) { if (this.list[name]) { delete this.list[name]; } } } let bus = new Bus(); export default bus; |
7) Vue.set
this.$set
废弃
8.) vuex 修改
1 2 |
import { createStore } from 'vuex'; export default createStore({...}) |
9) vue-router 修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// vue2 import Vue from 'vue'; import Router from 'vue-router'; Vue.use(Router); const router = new Router({ routes: [...] }) // 修改为: // vue3 import { createRouter,createWebHashHistory } from 'vue-router'; const router = new createRouter({ history: createWebHashHistory(), // 可有其它选项 routes: [...] }) |
据说完成以上几个方面的修改,大多数 vue2 项目即可完成技术栈到 vue3 的迁移。
参考链接:
– https://www.cnblogs.com/thinkingthigh/p/15529082.html
最后附上一个语法书写上的解释,对老夫这样的小白有用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
// 直接绑定法 Vue.prototype.$EventBus = new Vue() // 等于这种写法 const eve = new Vue() Object.defineProperty(Vue.prototype,'$bus',{ get() { return eve } }) // 等于这种写法 const eve = new Vue() Object.defineProperties(Vue.prototype, { $bus: { get() { return eve } } }) |