Vue 3 中如何優雅的使用eventBus(事件總線)
如果你剛開始使用Vue3,很可能會發現,原本用得得心應手的eventBus突然不靈了。
因為Vue3不再提供$on與emit函數,Vue實例不再實現事件接口。官方推薦引入外部工具實現,或者自己手擼一個事件類
api變更文檔:
Remove $on, $off and $once instance methods. Vue instances no longer implement the event emitter interface. -- active-rfcs/0020-events-api-change.md
如何使用
想在Vue3上把EventBus再次用起來也非常簡單,大體就是三個步驟
引入/編寫事件庫
在入口文件中掛載
在組件中引入並使用
🤡 先在前排推薦使用Vue3-Bus插件,后面會講如何不借助插件原生實現
- 通過Vue3-Eventbus使用更優雅 👍👍👍
不需要在入口文件中編寫額外邏輯,不需要每次引入inject函數,不需要每次為bus賦值,import進來一把梭直接用
安裝
$ npm install --save vue3-eventbus
復制代碼
掛載
import eventBus from 'vue3-eventbus'
app.use(eventBus)
復制代碼
使用
// Button.vue
import bus from 'vue3-eventbus'
export default {
setup() {
bus.emit('foo', { a: 'b' })
}
}
復制代碼
舒服了~
更多用法和配置可以參照github上的文檔
- 不借助插件的原生使用方式
- 引入/編寫事件庫
直接引入官方推薦的mitt
手擼一個簡單的發布/訂閱類
這兩種方式都沒啥差別,因為代碼邏輯也很簡單,貼一個代碼實現,可以直接copy去用
// eventBus.js
export default class EventBus{
constructor(){
this.events = {};
}
emit(eventName, data) {
if (this.events[eventName]) {
this.events[eventName].forEach(function(fn) {
fn(data);
});
}
}
on(eventName, fn) {
this.events[eventName] = this.events[eventName] || [];
this.events[eventName].push(fn);
}
off(eventName, fn) {
if (this.events[eventName]) {
for (var i = 0; i < this.events[eventName].length; i++) {
if (this.events[eventName][i] === fn) {
this.events[eventName].splice(i, 1);
break;
}
};
}
}
}
復制代碼
2. 在入口文件中執行掛載
入口文件默認是main.js
// main.js
import { createApp } from 'vue'
import App from './App.vue'
// ① 引入事件類
// 自己編寫的或者mitt皆可
import EventBus from 'lib/bus.js'
// 或者:import EventBus from 'mitt'
const $bus = new EventBus()
// ② 掛載
// 1.使用provide提供
app.provide('$bus', $bus)
// 2.掛載到this上
app.config.globalProperties.$bus = $bus
復制代碼
3. 在組件中引入並使用
在created中使用
// Button.vue
export default {
created() {
this.$bus.emit('ButtonCreated')
}
}
復制代碼
在setup中使用
注意: 因為在setup中無法訪問到應用實例(this),如果你需要在setup中使用eventBus,則需要通過provide/inject方式引入
// Button.vue
import { inject } from 'vue'
export default {
setup() {
const $bus = inject('$bus')
$bus.emit('ButtonSetup')
}
}
復制代碼
4. 使用小結
通過上面三個步驟,EventBus就可以正常使用啦,還是很簡單的。不過也能看到在掛載的時候需要多寫兩行代碼,使用的時候,每個組件在setup內都要引入inject函數,並且初始化一次。有朋友就要問了?有沒有更優雅的辦法咧?
沒錯!用了Vue3-Eventbus插件,只需要在入口文件里use一下,每個組件里引入就能直接用起來啦!