Vue2.x 使用 EventBus 进行组件通信,Vue3中事件总线模式已经被移除,官方建议推荐使用 mitt.js。
vue2通过创建一个空的vue实例作为全局事件总线,用它来触发事件和监听事件,从而实现任何组件间的通信,包括父子、隔代、兄弟组件。
//main.js
Vue.prototype.$eventBus = new Vue()
this.$eventBus.$emit( 'changeFunc' , 123, 'abc' )
//绑定前需先解绑,避免反复触发、内存泄漏的问题
this.$eventBus.$off( 'changeFunc' );
this.$eventBus.$on( 'changeFunc' , (val1, val2)=>{} )
缺点:如果绑定的事件过多的话,最好在总线处备注好所有绑定的事件名,便于维护。其实,如果真绑定那么多的话,最好还是不要用了,还不如老老实实用vuex呢。
mitt
- 首先它足够小,仅有200bytes。
- 其次支持全部事件的监听和批量移除。
- 它还不依赖 Vue 实例,可以跨框架使用,React 或者 Vue,甚至 jQuery 项目都能使用同一套库。
安装依赖
npm install --save mitt
挂载全局
import {createApp} from 'vue'
import {createPinia} from 'pinia'
import App from './App.vue'
import router from './router'
import './assets/main.css'
import mitt from 'mitt'
const Mit = mitt()
const app = createApp(App)
declare module 'vue' {
export interface ComponentCustomProperties {
$EventBus: typeof Mit
}
}
app.config.globalProperties.$EventBus = Mit
app.use(createPinia())
app.use(router)
app.mount('#app')
组件派发
<script setup lang="ts">
import {getCurrentInstance} from "vue";
const instance = getCurrentInstance()
const change = () => {
instance?.proxy?.$EventBus.emit('on-click', 'hello')
}
</script>
<template>
<h1>A:</h1>
<button @click="change">派发</button>
</template>
组件接受
<script setup lang="ts">
import {getCurrentInstance, ref} from "vue";
const flag = ref()
const instance = getCurrentInstance()
const bus = (str: any) => {
console.log("==>str", str)
flag.value = str
}
instance?.proxy?.$EventBus.on('on-click', bus)
</script>
<template>
<h1>B:{{flag}}</h1>
</template>