在vue2中兄弟组件传参可通过事件总线实现,具体方式为在Vue的原型上挂载事件总线,代码为:
// 入口文件main.js
Vue.prototype.$bus = new Vue()
在子组件中的用法为:
// 触发事件
this.$bus.$emit('eventName', params)
// 监听事件
this.$bus.$on('eventName', (...args) => {
// 函数体
})
在vue3中摒弃了Vue2中在Vue原型中挂载属性的方法,但是实现兄弟组件间通信方式的思路还是一致的,也是利用事件总线的方式,只是具体实现方式会有一点差别。
在vue3中使用mitt,具体的几种实现方式如下:
1. 在app.config.globalProperties挂载全局方法
// main.js
import mitt from 'mitt'
const app = createApp({})
app.config.globalProperties.$emitter = mitt()
// 组件内部
import { getCurrentInstance } from 'vue'
const { proxy } = getCurrentInstance()
// 监听事件
proxy.$emitter.on('foo', e => console.log('foo', e) )
// 触发事件
proxy.$emitter.emit('foo', { a: 'b' })
官方warning:
getCurrentInstance是一个内部的API,并不是公开的API,使用内部API去实现一些业务功能,可能会因为后续 Vue 的版本迭代而造成业务上的 BUG。并且 Vue3 的 Composition API 强调的就是业务的解耦和复用性,依赖组件实例属性并不是一个很好的开发方式。而 vue 相关生态的使用其实就是他们内部的事情了,他们有完善的测试用例可以跑测试,但是我们并没有,如果后续的某一个版本Vue变更了这个API,那么如果没有经过完整测试就部署上去的项目就会出现大规模的BUG反馈了
2. 使用provide 和 inject
// plugins/mitt.js
import mitt from 'mitt'
import { injectionMitt } from '../assets/js/keys'
export default {
install(app) {
app.provide(injectionMitt, mitt())
}
}
// assets/js/keys.js
export const injectionMitt = Symbol('mitt')
// 组件A
import { injectionMitt } from '../assets/js/keys';
const mittBus = inject(injectionMitt)
mittBus.on('mitt-plugin', (msg) => {
console.log('receive msg:', msg)
})
// 组件B
import { injectionMitt } from '../assets/js/keys';
const mittBus = inject(injectionMitt)
mittBus.emit('mitt-plugin', 'emit event by plugin way!')
3. 使用mitt的单例模式
// assets/js/mitt.js
import mitt from 'mitt'
export default mitt()
// 组件A
import mitt from '../assets/js/mitt'
mitt.on('foo', (...args) => {
console.log('args:', args)
})
// 组件B
import mitt from '../assets/js/mitt'
mitt.emit('foo', {
a: 1
})
mitt的具体使用方式:www.npmjs.com/package/mit…