Skip to content

介绍

EventBus是事件总线的意思,其实就和发布订阅模式非常类似,在一个地方通过on方法注册一个事件,然后在其他页面通过emit方法远程调用之前on里面注册的方法。EventBus经常用到跨组件通信。

实现

在Vue2里面可以直接通过以下方法创建事件总线(又叫EventBus或者EventEmitter)

const EventBus = new Vue()
const EventBus = new Vue()

在Vue3以后,就不可以通过以上方式来创建EventBus了,所以我们不妨自己来写一个。 以下是一个网上参考版本

ts
// eventBus.ts
class EventBus {
    constructor() {
        this.eventList = new Map();
    }
    // 注册时间
    on(event, callback) {
        if(!this.eventList.has(event)) {
            this.eventList.set(event, []);
        }
        this.eventList.get(event).push(callback);
    }
    // 触发时间
    emit(event, ...args) {
        if(this.eventList.has(event)) {
            this.eventList.get(event).forEach(listener => listener(...args));
        }
    }
    // 注销事件
    off(event, callback) {
        if(this.eventList.has(event)) {
            if(callback) {
                const newEventList = this.eventList.get(event).filter(listener => listener !== callback));
                this.eventList.set(event, newEventList);
            }
        }
    }
    // 只执行一次
    once(event, callback) {
        let once = (...args) => {
            callback(...args);
            this.off(event, once);
        }
        this.on(event, once);
    }
}
export const bus = new EventBus();
// eventBus.ts
class EventBus {
    constructor() {
        this.eventList = new Map();
    }
    // 注册时间
    on(event, callback) {
        if(!this.eventList.has(event)) {
            this.eventList.set(event, []);
        }
        this.eventList.get(event).push(callback);
    }
    // 触发时间
    emit(event, ...args) {
        if(this.eventList.has(event)) {
            this.eventList.get(event).forEach(listener => listener(...args));
        }
    }
    // 注销事件
    off(event, callback) {
        if(this.eventList.has(event)) {
            if(callback) {
                const newEventList = this.eventList.get(event).filter(listener => listener !== callback));
                this.eventList.set(event, newEventList);
            }
        }
    }
    // 只执行一次
    once(event, callback) {
        let once = (...args) => {
            callback(...args);
            this.off(event, once);
        }
        this.on(event, once);
    }
}
export const bus = new EventBus();

使用方法

以下演示一下在Vue3中的使用方法

ts
// a.vue
<script>
import { bus } from '@/units/eventBus';

const showDialog = ref(false);

onMounted(() => {
    bus.on('showDialog', (visible: boolean) => {
        showDialog.value = visible
    })
})
</script>

<template>
    <Dialog v-if="showDialog" />
</template>
// a.vue
<script>
import { bus } from '@/units/eventBus';

const showDialog = ref(false);

onMounted(() => {
    bus.on('showDialog', (visible: boolean) => {
        showDialog.value = visible
    })
})
</script>

<template>
    <Dialog v-if="showDialog" />
</template>
ts
// b.vue
<script>
import { bus } from '@/units/eventBus';

const handleClick = () => {
    bus.emit('showDialog', true);
}
</script>

<template>
    <button @click="handleClick">test</button>
</template>
// b.vue
<script>
import { bus } from '@/units/eventBus';

const handleClick = () => {
    bus.emit('showDialog', true);
}
</script>

<template>
    <button @click="handleClick">test</button>
</template>

以上案例,当按钮点击的时候,将会触发EventBus,展示Dialog组件,实现远程控制组件的加载。

Released under the MIT License.