Skip to main content

mitt

简介

优点

  • 零依赖、体积超小,压缩后只有200b。
  • 提供了完整的typescript支持,能自动推导出参数类型。
  • 基于闭包实现,没有烦人的this困扰。
  • 为浏览器编写但也支持其它javascript运行时,浏览器支持ie9+(需要引入Map的polyfill)。与框架无关,可以与任何框架搭配使用。

基础使用

安装

yarn add mitt

引入

  • js
import mitt from "mitt";

const mittBus = mitt();

export default mittBus
  • ts
import mitt from 'mitt';
import type { SettingPageValue } from '@/stores';
import type { SaveDialogOptions, OpenDialogOptions } from 'electron';
import type { SettingKeyVal } from '@/global';

/* 事件声明 */
type EventBus = {
imageCuterMenuClick: string;
imageCuterSave: string;
imageCuterTabcropDraw: string;
imageCuterSettings: boolean;
imageCuterBodyOpenFile: string;
imageCuterChangeSetting: SettingKeyVal;

bodyUpdateReiszeCoords: string;

showSettingsPage: SettingPageValue;
mainOpenFolder: SaveDialogOptions | OpenDialogOptions;
};

// 初始化一个 mitt 实例
export const eventBus = mitt<EventBus>();

// 可以在内部先定义一些事件
eventBus.on('mainOpenFolder', window.electron.openDialog);

// 在导出时使用旧的 API 名称去调用 mitt 的 API
export default eventBus;

使用案例

基础语法

  • vue3
// 接收数据组件
<script setup lang="ts">
import {onUnmounted} from "vue";
import mittBus from '../../hooks/mittBus.js'
// 监听时间方法
const callback = (test:string) => {
console.log(test)
}

mittBus.on('form-item-created',callback)

// 用完后要清理监听器
onUnmounted(()=>{
mittBus.off('form-item-created',callback)
})
</script>
// 发送数据组件
<script setup lang="ts">
import {onMounted} from "vue";
import mittBus from '../../hooks/mittBus.js'

onMounted(()=>{
mittBus.emit('form-item-created',inputRef.val)
})
</script>

通过全局调用(import|export)

// main.ts
import emitter from "@/utils/emitter";

// 挂载在全局上
app.config.globalProperties.$emitter = emitter

// 由于必须要拓展ComponentCustomProperties类型才能获得类型提示
declare module "vue" {
export interface ComponentCustomProperties {
$emitter: typeof emitter;
}
}
// App.vue 中使用, 非 setup script 语法糖
<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
...
mounted() {
this.$emitter.on("foo", () => {
//do something
});
},
...
});
</script>

// App.vue 中使用, setup script 语法糖
<script lang="ts" setup>
import { getCurrentInstance } from "vue";
const instance = getCurrentInstance();
instance?.proxy?.$emitter.on("foo", () => {
// dosomething
});

组件级的局部调用(inject|provide)

  • Parent.vue
<script lang="ts">
import { InjectionKey } from "vue";
import mitt, { Emitter } from "mitt";
type Events = {
foo: string;
bar: number;
};
// 为了拥有类型化提示,必须多使用一个<srcpit></script>标签
要导出一个类型化的key
export const emitterKey: InjectionKey<Emitter<Events>> = Symbol("emitterKey");
</script>

<script lang="ts" setup>
import { provide } from "vue";
const emitter = mitt<Events>();
provide(emitterKey, emitter);
</script>