在Vue3中使用发布订阅

在 Vue 3 中,官方不再内置类似于 Vue 2 中的全局事件总线($on$off$emit)功能,而是鼓励开发者使用更显式的方式(如 propsprovide/inject 或外部状态管理库如 Pinia)来处理组件通信。然而,发布-订阅模式(Publish-Subscribe Pattern)仍然是一种非常有效的组件间通信方式,尤其适用于非父子关系的组件通信场景。在 Vue 3 中,我们可以通过自定义实现一个事件总线(Event Bus)来应用发布-订阅模式。

下面我将详细讲解 Vue 3 中发布-订阅模式的实现原理、使用方式,并结合 Vue 3 的特性(如 Composition API)提供示例。


1. Vue 3 中发布-订阅的背景

  • Vue 2 的实现:Vue 2 中可以通过 Vue.prototype.$bus = new Vue() 创建一个全局事件总线,利用 $emit 发布事件,$on 订阅事件。
  • Vue 3 的变化:Vue 3 移除了实例上的 $on$off$once 方法,因此不能直接用 Vue 实例作为事件总线。
  • 替代方案
  • 使用独立的 JavaScript 类实现事件总线。
  • 结合 Composition API 或第三方库(如 mitttiny-emitter)实现。

2. 自定义实现发布-订阅

我们可以通过创建一个简单的 EventBus 类来实现发布-订阅模式,并在 Vue 3 项目中使用。

EventBus 实现:

说明:

  • on:订阅事件,将回调函数添加到指定事件。
  • emit:发布事件,触发所有订阅者的回调。
  • off:取消订阅,移除特定回调。
  • once:一次性订阅,事件触发后自动取消。

3. 在 Vue 3 中使用

我们可以在 Vue 3 项目中引入这个 EventBus,并在组件中使用它。

示例:组件间通信

假设有两个组件 ComponentA(发布者)和 ComponentB(订阅者),它们通过事件总线通信。

输出:

  • 点击 ComponentA 的按钮后,ComponentB 会显示:收到消息: Hello from ComponentA!

4. 结合 Composition API

为了更好地封装发布-订阅逻辑,我们可以使用 Composition API 创建一个可复用的 useEventBus 组合函数。

实现 useEventBus

使用:

优势:

  • 自动清理:通过 onMountedonUnmounted,确保组件销毁时自动取消订阅,避免内存泄漏。
  • 可复用useEventBus 可以在多个组件中复用,减少重复代码。

5. 使用第三方库

如果你不想自己实现,可以使用现成的轻量级库:

  • mitt:一个非常流行的微型事件发射器。
  • 安装:npm install mitt
  • 使用:

6. 与插槽的关系

发布-订阅模式可以与 Vue 3 的插槽结合使用。例如,子组件通过插槽暴露数据,父组件通过事件总线触发更新:


7. 优缺点

优点:

  • 解耦:组件间无需直接依赖。
  • 灵活:适用于跨层级或动态组件通信。
  • 简单:实现和使用都相对直观。

缺点:

  • 调试困难:事件多了可能难以追踪来源。
  • 官方不推荐全局使用:Vue 3 更推崇 propsprovide/inject 或状态管理。

8. 总结

Vue 3 中发布-订阅模式可以通过自定义 EventBus 或第三方库实现,结合 Composition API 可以更优雅地管理订阅和清理。它特别适合非父子组件通信,但在大型应用中应谨慎使用,避免过度依赖全局事件总线。