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>