Vue3 数据总线的实现
在 Vue 开发中,组件通信 是一个非常重要的主题。对于父子组件之间的通信,我们可以通过 props/emit 来实现。然而,在 非父子组件 或 兄弟组件 之间进行通信时,传统的 props/emit 就显得力不从心了。这时,事件总线(Event Bus) 就派上了用场。
在 Vue 2 中,我们可以通过 new Vue() 创建一个事件总线实例,并使用 $emit、$on 和 $off 来实现事件的发布与订阅。然而,在 Vue 3 中,这些 API 被移除了。幸运的是,我们可以借助一个轻量级的开源库 —— mitt 来实现类似的功能。
什么是mitt?
mitt 是一个极简的JavaScript事件发布/订阅库,体积仅有200字节左右,但却功能强大。它可以在任何 JavaScript 环境中使用,包括 Vue、React 甚至原生 JS。mitt 的核心功能非常简单:
- 发布事件:通过
emit方法触发事件。 - 订阅事件:通过
on方法监听事件。 - 取消订阅:通过
off方法移除事件监听器。
如何在 Vue 3 中使用mitt?
1、安装mitt
首先,我们需要通过 npm 安装 mitt:
npm i mitt
2、创建事件总线
接下来,我们创建一个事件总线实例
import mitt from "mitt"; const emitter = mitt(); export default emitter;
3、在组件中订阅事件
<template>
<div>
<div>Bar: {{ date }}</div>
</div>
</template>
<script setup lang="ts">
import { onBeforeMount, onMounted, ref } from 'vue';
import emitter from './emitter';
const date = ref()
onMounted(() => {
emitter.on('bar', (data) => {
date.value = data
})
})
onBeforeMount(() => {
emitter.off('bar')
})
</script>
4、在组件中发布事件
// Foo.vue
<template>
<div>
<span>Foo: </span>
<button @click="click">触发事件</button>
</div>
</template>
<script setup lang="ts">
import emitter from './emitter';
function click() {
emitter.emit('bar', new Date().toLocaleString());
}
</script>
mitt实现原理
miit的原理其实非常简单,主要依赖于一个 Map 对象来存储事件类型及其对应的处理函数。以下是mitt的简化实现:
function mitt() {
const all = new Map();
return {
// 订阅事件
on(type, handler) {
const handlers = all.get(type)
if (handlers) {
handlers.push(handler)
} else {
all.set(type, [handler])
}
},
// 取消订阅
off(type, handler) {
const handlers = all.get(type)
if (!handlers) {
return
}
if (handler) {
const index = handlers.indexOf(handler)
if (index > -1) {
handlers.splice(index, 1)
}
} else {
all.set(type, [])
}
},
// 发布事件
emit(type, ...args) {
const handlers = all.get(type);
handlers?.slice().map(handler => {
handler(...args)
})
}
}
}
到此这篇关于Vue3 数据总线的实现的文章就介绍到这了,更多相关Vue3 数据总线内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
解决Element组件的坑:抽屉drawer和弹窗dialog
这篇文章主要介绍了解决Element组件的坑:抽屉drawer和弹窗dialog问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教2024-07-07


最新评论