Vue3开发极简入门(17):无关联组件间通信之mitt

Vue3开发极简入门(17):无关联组件间通信之mitt

精选文章moguli202025-07-06 14:58:532A+A-

前面介绍的,父子、爷孙组件通信方式,要想解决子子、孙孙间通信,两个无关联组件的通信还是太麻烦的。

mitt可适用于任意组件间的通信。

对于后端的开发同学来说,mitt可以类比Kafka,一个基于发布/订阅模式的消息队列。


安装mitt:

npm i mitt

创建一个全局的emitter文件,src/utils/emitter.ts:

import mitt,{type Emitter} from "mitt";
type Events={
    sayToSon1:string,
    sayToSon2?:string,
    sayToAll:string
}
const emitter: Emitter<Events> = mitt<Events>();
// 不同Emitter的写法
// const emitter = mitt<Events>();
export default emitter
  • Events就是所有Topic的集合。
  • sayToAll就是Topic。后面的string代表此事件回调函数要传入的参数类型。string、number、对象都可以。?代表参数可选。

很多时候搜索资料,网上给出的多是js的写法,超简单:

import mitt from 'mitt';
const emitter = mitt();
export default emitter;

但是,TypeScript对类型要求严格,本文还是用TS的写法。


写一个父组件,两个子组件。父组件没什么用,就是引入一下两个子组件,代码就不放了。

两个子组件代码基本一致。

Son1.vue:

<template>
    <div class="son1">
        <h1>子1组件</h1>
        消息:<div v-html="msgToMe"></div>
        <br>
        <button @click="sayToSon2">向Son2说话</button>
        <button @click="sayToAll">向所有人说话</button>
    </div>
</template>
<script lang='ts' setup name='Son1'>
import { onBeforeUnmount, onMounted, ref } from 'vue';
import emitter from '@/utils/emitter';
const msgToMe = ref("")

function sayToSon2() {
    emitter.emit('sayToSon2', "Son1向Son2说:" + Math.random())
}
function sayToAll() {
    emitter.emit('sayToAll', "Son1向所有人说:" + Math.random())
}

const sayToSon1 = (msg: string) => {
    msgToMe.value = msgToMe.value + "<br/>" + msg
}

onMounted(() => {
    emitter.on('sayToSon1', sayToSon1)
    emitter.on('sayToAll', sayToSon1)
})

onBeforeUnmount(() => {
    emitter.all.clear
})
</script>
<style scoped>
.son1 {
    background-color: silver;
    padding: 10px;
    margin-top: 10px;
    box-shadow: 0 0 10px black;
    border-radius: 10px;
    width: 80%;
    margin: auto;
}
</style>

Son2.vue:

<template>
    <div class="son2">
        <h1>子2组件</h1>
        消息:<div v-html="msgToMe"></div>
        <br>
        <button @click="sayToSon1">向Son1说话</button>
        <button @click="sayToAll">向所有人说话</button>
    </div>
</template>
<script lang='ts' setup name='Son2'>
import { onBeforeUnmount, onMounted, ref } from 'vue';
import emitter from '@/utils/emitter';
const msgToMe = ref("")

function sayToSon1() {
    emitter.emit('sayToSon1', "Son2向Son1说:" + Math.random())
}
function sayToAll() {
    emitter.emit('sayToAll', "Son2向所有人说:" + Math.random())
}

const sayToSon2 = (msg?: string) => {
    msgToMe.value = msgToMe.value + "<br/>" + msg
}

onMounted(() => {
    emitter.on('sayToSon2', sayToSon2)
    emitter.on('sayToAll', sayToSon2)
})

onBeforeUnmount(() => {
    emitter.off('sayToSon2')
    emitter.off('sayToAll')
})
</script>
<style scoped>
.son2 {
    background-color: skyblue;
    padding: 10px;
    margin-top: 10px;
    box-shadow: 0 0 10px black;
    border-radius: 10px;
    width: 80%;
    margin: auto;
}
</style>

注意:

  • on是订阅事件,一般在页面加载的时候进行。emitter.on(Topic名,回调函数)。
  • off是取消订阅事件,all.clear是取消订阅所有事件。要在页面卸载的时候取消订阅,防止内存泄露。
点击这里复制本文地址 以上内容由莫古技术网整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!
qrcode

莫古技术网 © All Rights Reserved.  滇ICP备2024046894号-2