情景描述
在我们开发逻辑复杂的需求时,难免会遇到一个主组件中封装了N个子组件,他们之间还必须保持着些许联动。下面分享个 我在vue2,及vue3中怎么实现的。
vue2
在某个目录下创建个 eventBus.js(名字可以随便起)
eventBus.js 中代码如下:
import Vue form 'vue'
export default new Vue()
项目中引用:
/**A子组件 xx 是src下的某个目录 */
import EventBus from "@/xx/eventbus"
// 某个事件触发时
const targetEvent = () => {
EventBus.$emit("on-submit",{name: '奇迹行者'})
}
/**B子组件 xx 是src下的某个目录 */
import EventBus from "@/xx/eventbus"
// 监听eventBus 触发的事件
created(){
EventBus.$on("on-submit", (obj) => { console.log('这里是接受传过来的对象,做一些操作') })
}
vue3
vue3 我们一般用第三方插件 mitt来实现。下面是项目中手写的mitt。
//在src新建个utils文件夹并添加文件mitt.ts
class Mitt {
private readonly emitter: Record<string, Array< (value: any) => void>> = {}
// on 事件
on(eventName: string,cb:(value: any) => void){
this.emitter[eventName] ? this.emitter[eventName].push(cb): this.emitter[eventName] = [cb]
};
// emit 事件
emit(eventName: string, value: any) {
if(this.emitter[eventName]) {
this.emitter[eventName].forEach(cb => cb(value))
}
}
//off 事件
off(eventName: string, cb?: () => void):void {
delete this.emitter[eventName]
if(cb) cb();
}
// offAll 事件
offAll(){
Object.keys(this.emitter).forEach(key => {
delete this.emitter[key]
})
}
}
export const eventBus = new Mitt();
用法举例:
// A组件
import { eventBus } from "@/utils/mitt";
const sendMessage = () => {
eventBus.emit('message','你好呀')
}
// B组件
import { eventBus } from "@/utils/mitt";
const msg = ref()
onMounted( () => {
eventBus.on('message', (data:any) => {
msg.value = data
})