事件总线在应用开发中是常用的模式。
Vue.js在升级到v3之后,相对v2有较大改变,事件总线的实现方式也有所有调整。
首先Vue3中 事件API 有较大的修改。点击查看
我们从实例中完全移除了
$on
、$off
和$once
方法。$emit
仍然包含于现有的 API 中,
因为它用于触发由父组件声明式添加的事件处理函数。
另外,全局变量的设置方式也有调整:
// vue2
Vue.prototype.$EventBus = new Vue();
// Vue3
import { createApp } from 'vue';
const app = createApp({});
app.config.globalProperties.$EventBus = createApp({});
因为Vue3中对事件API进行的修改,所以无法用类似Vue2的那种new一个实例对象用作全局的事件总线。
此处可以引入一个单独的库 mitt用于实现事件总线。
例子包含三个文件:
main.ts
// main.ts
import { createApp } from 'vue';
// 引入mitt
import mitt, { Emitter } from 'mitt';
const mitter: Emitter = mitt();
const app = createApp(App);
// 加入全局变量中
app.config.globalProperties.mitter = mitter;
app.mount('#app');
a.vue
// a.vue
<script lang="ts">
export default defineComponent({
// 拿到mitter
const mitter = getCurrentInstance()?.appContext.config.globalProperties.mitter;
// emit自定义事件
mitter.emit('customEvent')
})
</script>
b.vue
// b.vue
<script lang="ts">
export default defineComponent({
// 拿到mitter
const mitter = getCurrentInstance()?.appContext.config.globalProperties.mitter;
// 监听自定义事件
mitter.on('customEvent', () => console.log('i got customEvent')
})
</script>
或者也可以使用 Provide/Inject
main.ts
...
// 将设置全局改成设置provide
app.provide('mitter', mitter)
// 不能写成这样,因为这样在App.vue中会使用inject会拿不到mitter
const app = createApp({
...App,
provide() {
return {
mitter
}
}
})
a.vue/b.vue
import { Emitter } from 'mitt';
...
// 在sfc中,要使用as增加类型推导, 不然ts会判断得到的mitter的类型是unknown
const mitter = inject('mitter') as Emitter;
以上,就可以完成在Vue3中配置 事件总线 模式。
网友评论