vue的事件总线

174 阅读1分钟

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

  1. 首先它足够小,仅有200bytes。
  2. 其次支持全部事件的监听和批量移除。
  3. 它还不依赖 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>