vue3 借用mitt实现兄弟组件传参

245 阅读1分钟

在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…