浅析eventbus,并尝试在vue3中手写一个

1,325 阅读1分钟

eventbus在vue2中实现非常简单,只需要注册一个vue实例,并且挂载在vue的原型对象上面

import Vue from 'vue'
Vue.prototype.$bus = new Vue()

1.发出事件 => $emit 2.监听事件 => $on 3.销毁事件 => $off

eventBus在vue3中使用起来差不多,但是因为Vue3不再提供$onemit函数,Vue实例不再实现事件接口,需要使用插件或者自己写一个

先说说插件,用的比较多的就是vue3-eventbus 还有mitt,详细用法可以看官网

需要手写也很简单,而且可以通过eventBus理解发布订阅模式,推荐大家试一试

   export default class EventBus{
    constructor(){
        // 一个数组,存放callback的地方,格式为 事件名:回调函数数组
        this.events = {}
    }
    // 发布
    emit(eventName, ...data) {
         // 通过可选链运算符,跳过判断直接遍历调用
         this.events[eventName]?.forEach(callback => {
             callback(...data)
         })
    }
    // 订阅
    on(eventName, callback) {
        // 用一个三元简单判断一下有无注册事件,有则push,无则添加
        console.log('eventName', eventName);
        this.events[eventName] ?
        this.events[eventName].push(callback) :
        this.events[eventName] = [callback]
    }
    // 取消订阅
    off(eventName, callback) {
        if (this.events[eventName]) {
            for(let i of this.events[eventName]) {
                if(this.events[eventName][i] === callback) {
                    delete this.events[eventName][i]
                    return
                }
            }
        }
    }
}

在main.js中引入

import EventBus from './utils/eventBus'
const eventBus = new EventBus()
// 通过注入提供eventBus
app.provide('$bus', eventBus)

在父组件

<script setup>
import { inject } from 'vue';
import EventBusSon from './components/eventBusSon.vue';

    const bus = inject('$bus')
    const aa = () => {
        bus.emit('a', 1)
    }
</script>

<template>
    <EventBusSon></EventBusSon>
    <button @click="aa">123</button>
</template>

在子组件

<script setup>
import { inject } from 'vue';

const bus = inject('$bus')
console.log(bus);
bus.on('a', (val) => {
    console.log(val);
})
</script>