Vue3中mitt实现eventBus(个人笔记)

在 Vue 2 里,开发者常常使用 event bus 来处理非父子组件之间的通信。不过,这种方式在大型项目中容易让代码变得难以维护,因为事件的流向和触发位置会变得不清晰。Vue 3 推荐采用组合式 API 和 provide/inject、Vuex(状态管理库)、Pinia(状态管理库)等方式来实现组件间的通信,这些方式能让代码结构更加清晰,易于维护。

如果仍需要使用event bus,可以使用轻量级的事件发布 - 订阅库 mitt 来实现 event bus 功能,它可以帮助你实现组件间的通信和解耦。下面详细介绍 mitt 的使用方法。

安装


npm install mitt

在项目中使用


1. 创建全局事件总线

在 Vue 项目中,你可以创建一个全局的事件总线,方便在不同组件之间进行通信。

// event-bus.js
import mitt from 'mitt';

// 创建一个 mitt 实例作为事件总线
const eventBus = mitt();

export default eventBus;

2. 在组件中使用事件总线

<!-- ComponentA.vue -->
<template>
    <div>
        <button @click="sendMessage">发送消息</button>
    </div>
</template>

<script setup>
import eventBus from './event-bus';

const sendMessage = () => {
    // 发布事件
    eventBus.emit('message', '来自 ComponentA 的消息');
};
</script>
<!-- ComponentB.vue -->
<template>
    <div>
        <!-- 显示接收到的消息 -->
        <p>{{ receivedMessage }}</p>
    </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import eventBus from './event-bus';

const receivedMessage = ref('');

const handleMessage = (data) => {
    receivedMessage.value = data;
};

onMounted(() => {
    // 订阅事件
    eventBus.on('message', handleMessage);
});

onUnmounted(() => {
    // 取消订阅事件
    eventBus.off('message', handleMessage);
});
</script>

取消订阅事件


使用 off 方法可以取消订阅事件,该方法接受两个参数:事件名称和要取消的回调函数。

// 定义回调函数
const handleMessage = (data) => {
    console.log('收到消息:', data);
};

// 订阅事件
emitter.on('message', handleMessage);

// 取消订阅事件
emitter.off('message', handleMessage);

清空所有事件监听器


使用 all.clear() 方法可以清空所有的事件监听器。

// 清空所有事件监听器
emitter.all.clear();

案例


有了发布-订阅事件,我们就可以实现在封装好的js文件中发布事件,在页面中订阅事件了。例如我封装了webSocket.js,在收到新消息的时候发布事件携带消息,然后在页面中订阅拿到新消息。

webSocket.js

import bus from "@/utils/bus";
export class Socket {
  constructor(url) {
    this.url = url;
    this.socket = null;
  }
  connectSocket() {
    // 监听WebSocket打开连接
    this.socket.onopen = () => {
      console.log("WebSocket连接打开成功!");
    };
    // 监听WebSocket错误
    this.socket.onerror = (res: any) => {
      console.log("WebSocket连接打开失败,请检查!", res);
    };
    // 监听WebSocket接受到服务器的消息
    this.socket.onmessage = (res: any) => {
      console.log("收到服务器内容:", res.data);
      const data = JSON.parse(res.data);
      bus.emit("newMessage", data.message);
    };
  }
  ...
}

message.vue

在message.vue中订阅新消息

import bus from "@/utils/bus";
onMounted(() => {
  const socket = new Socket("wss://xxx");
  messageStore.messageSocket = socket;
  socket.connectSocket();
  // 收到新消息弹出消息通知
  bus.on("newMessage", (data: any) => {
    ElNotification({
      title: data.title,
      message: data.content
    });
  });
});
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容