我们在组件的传参方式中讲解了组件的基本传参方式,但是显示场景中,会遇到复杂的情况。
但是官方文档并没有直接推荐或提及事件总线(Event Bus)作为一种组件间通信的官方方式。这是因为事件总线可能会引入全局状态管理的问题,使得应用的状态难以追踪和理解,尤其是在大型项目中。然而,在某些小规模的项目或特定的场景中,事件总线仍然可以作为一种简单快速的通信手段。
事件总线的基本思想
事件总线是一个自定义的 Vue 实例,充当了一个中央事件广播系统。任何组件都可以在这个总线上触发事件或监听事件。
// event-bus.ts
import { createApp } from 'vue'; // 创建一个空的 Vue 实例作为事件总线
const EventBus = createApp({}).mount(null); export default EventBus;
然后,在需要使用事件总线的组件中,我们可以通过 import
引入它,并使用 $emit
来触发事件,使用 $on
来监听事件。
<template> <button @click="sendEvent">发送事件</button>
</template> <script setup lang="ts">
import { ref } from 'vue';
import EventBus from '@/event-bus'; // 假设 event-bus.ts 文件位于 src 目录下 const sendEvent = () => { // 使用 $emit 触发一个名为 'custom-event' 的事件,并传递一些数据 EventBus.$emit('custom-event', { message: 'Hello from Event Bus!' });
}; // 在组件挂载后监听事件
onMounted(() => { EventBus.$on('another-event', (data) => { console.log('Received data from another event:', data); });
}); // 在组件卸载前移除事件监听器,避免内存泄漏
onBeforeUnmount(() => { EventBus.$off('another-event');
});
</script>
在另一个组件中,我们可以监听这个 custom-event
:
<template> <div v-if="eventReceived">Received: {{ eventMessage }}</div>
</template> <script setup lang="ts">
import { ref, onMounted, onBeforeUnmount } from 'vue';
import EventBus from '@/event-bus'; const eventReceived = ref(false);
const eventMessage = ref(''); // 在组件挂载后监听事件
onMounted(() => { EventBus.$on('custom-event', (data) => { eventReceived.value = true; eventMessage.value = data.message; });
}); // 在组件卸载前移除事件监听器
onBeforeUnmount(() => { EventBus.$off('custom-event');
});
</script>
注意事项
全局状态管理:事件总线模式引入了一种全局状态管理的方式,这可能会使得应用的状态难以追踪和理解。对于复杂的应用,建议使用 Vuex 或 Pinia 这样的状态管理库。
内存泄漏:在使用事件总线时,必须确保在组件卸载时移除所有事件监听器,以避免内存泄漏。
替代方案:Vue 3 提供了
provide
和inject
API,以及 Teleport 和 Suspense 这样的新特性,这些都是更现代和可维护的组件间通信方式。