Vue笔记(十二)--mitt

这一节了解一下Vue3中的mitt,mitt是Vue3中最常用的轻量级事件总线库,本质是一个基于发布-订阅模式的独立EventEmitter,总结如下:

API:

emitter.on(event, handler):监听事件,注册回调函数,当事件触发时执行

emitter.emit(event, data):触发事件,发布事件并携带数据,通知所有监听者

emitter.off(event, handler):取消监听, 移除指定事件的指定回调,防止内存泄漏

emitter.all.clear():清空所有监听,一次性移除所有事件的所有回调

场景

1 兄弟组件/非父子组件通信:两个无直接关系的组件需要传递消息。

2 全局通知/消息提示:任意组件触发全局Toast、Notification等。

3 跨多层组件传递消息:避免props逐层透传。

栗子:

TypeScript 复制代码
src/utils/eventBus.ts

import mitt from 'mitt'

const emitter = mitt()
export default emitter
TypeScript 复制代码
发送方BrotherA.vue

<template>
  <div style="border:1px solid #ccc;padding:10px;margin:8px;">
    <h3>兄弟A(发送方)</h3>
    <button @click="sendMsg">给兄弟B发送消息</button>
  </div>
</template>

<script setup lang="ts">
import emitter from '@/utils/eventBus'

const sendMsg = () => {
  emitter.emit('send-to-b', {
    name: '兄弟A',
    content: '你好,我是A组件消息'
  })
}
</script>
TypeScript 复制代码
接收方 BrotherB.vue

<template>
  <div style="border:1px solid #ccc;padding:10px;margin:8px;">
    <h3>兄弟B(接收方)</h3>
    <p>收到消息:{{msg}}</p>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount } from 'vue'
import emitter from '@/utils/eventBus'

const msg = ref('')

onMounted(() => {
  emitter.on('send-to-b', (data) => {
    msg.value = `${data.name}:${data.content}`
  })
})


onBeforeUnmount(() => {
  emitter.off('send-to-b')
})
</script>
TypeScript 复制代码
App.vue

<template>
  <BrotherA />
  <BrotherB />
</template>

<script setup lang="ts">
import BrotherA from './components/BrotherA.vue'
import BrotherB from './components/BrotherB.vue'
</script>

Demo2

TypeScript 复制代码
src/utils/eventBus.ts

import mitt from 'mitt'

type EventType = {
  'submit-form': { username: string; password: string }
  'global-notice': string
}

const emitter = mitt<EventType>()
export default emitter
TypeScript 复制代码
src/composables/useEventBus.ts

import emitter from '@/utils/eventBus'
import { onBeforeUnmount } from 'vue'

export function useEventBus() {
  const handlers: Array<() => void> = []

  const on = <T extends keyof EventType>(event: T, callback: (data: EventType[T]) => void) => {
    emitter.on(event, callback)
    handlers.push(() => emitter.off(event, callback))
  }

  const emit = <T extends keyof EventType>(event: T, data: EventType[T]) => {
    emitter.emit(event, data)
  }

  onBeforeUnmount(() => {
    handlers.forEach(unbind => unbind())
  })

  return { on, emit }
}
TypeScript 复制代码
FormSubmit.vue

<template>
  <div style="border:1px solid #ccc;padding:12px;">
    <h3>表单组件</h3>
    <input v-model="form.username" placeholder="用户名"/>
    <input v-model="form.password" placeholder="密码"/>
    <button @click="handleSubmit">提交表单</button>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { useEventBus } from '@/composables/useEventBus'

const { emit } = useEventBus()
const form = ref({
  username: '',
  password: ''
})

const handleSubmit = () => {
  emit('submit-form', form.value)
  emit('global-notice', '表单已提交成功!')
}
</script>
TypeScript 复制代码
GlobalTip.vue

<template>
  <div style="border:1px solid #42b983;padding:12px;margin-top:10px;">
    <h3>全局提示组件</h3>
    <p>表单数据:{{formInfo}}</p>
    <p>通知消息:{{tipMsg}}</p>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { useEventBus } from '@/composables/useEventBus'

const { on } = useEventBus()
const formInfo = ref('')
const tipMsg = ref('')

on('submit-form', (data) => {
  formInfo.value = `用户名:${data.username},密码:${data.password}`
})

on('global-notice', (msg) => {
  tipMsg.value = msg
})
</script>
TypeScript 复制代码
App.vue

<template>
  <FormSubmit />
  <GlobalTip />
</template>

<script setup lang="ts">
import FormSubmit from './components/FormSubmit.vue'
import GlobalTip from './components/GlobalTip.vue'
</script>

注意:

1 必须手动取消监听:组件卸载时务必调用off移除回调,否则回调函数会一直驻留内存,导致内存泄漏。

2 事件命名冲突:事件名是全局字符串,建议加命名空间前缀,避免不同模块间冲突。

相关推荐
海鸥-w24 分钟前
数据库冗余字段设计笔记
java·数据库·笔记·oracle
滴啦嘟啦哒1 小时前
【具身笔记】【原理探究】一、对PI05源码的实践笔记
笔记·python·vla·具身
山雀~1 小时前
CSP 安全漏洞修复
前端·网络协议
陌离2 小时前
Go-Gui:一套 无限接近 现代化UI的 GPU绘制界面组件框架
前端
咚咚咚小柒2 小时前
【前端】LangChain.js学习
前端·javascript·人工智能·typescript·langchain·vue·ai编程
2401_885885042 小时前
巴林语音通知接口如何对接?系统告警语音API接入教程
android·前端·网络·python·语音识别
java1234_小锋2 小时前
【技术专题】CSS3 网页技术 - CSS3 盒模型
前端·css·css3
计算机魔术师2 小时前
手握芯片、又要吞下开源分发入口,英伟达被盯上了
前端
览讯冷却3 小时前
冷却塔噪声的健康危害与法规要求的技术梳理
经验分享·笔记·科技·其他·百度·制造·业界资讯
段一凡-华北理工大学3 小时前
高炉能源系统智能化:热风炉、煤气与极致能效~系列文章07:高炉煤气:产生规律与全厂用户平衡
java·前端·能源