事件總線Mitt使用非常簡單,本篇隨筆介紹在Vue3+TypeScript 前端專案中使用的一些場景和思路,我們在Vue 的專案中,經常會通過emits 觸發事件來通知組件或者頁面進行相應的處理,不過我們使用事件總線Mitt來操作一些事件的處理,也是非常方便的,
Mitt 的GitHub官網地址如下所示:https://github.com/developit/mitt, 它的安裝和其他插件一樣,我們不再贅述,只講述它的如何使用,
Mitt 具有以下優點:
- 零依賴、體積超小,壓縮后只有
200b, - 提供了完整的
typescript支持,能自動推匯出引數型別, - 基于閉包實作,沒有煩人的
this困擾, - 為瀏覽器撰寫但也支持其它
javascript運行時,瀏覽器支持ie9+(需要引入Map的polyfill), - 與框架無關,可以與任何框架搭配使用,
import mitt from 'mitt' const emitter = mitt() // 訂閱一個具體的事件 emitter.on('foo', e => console.log('foo', e) ) // 訂閱所有事件 emitter.on('*', (type, e) => console.log(type, e) ) // 發布一個事件 emitter.emit('foo', { a: 'b' }) // 根據訂閱的函式來取消訂閱 function onFoo() {} emitter.on('foo', onFoo) // listen emitter.off('foo', onFoo) // unlisten // 只傳一個引數,取消訂閱同名事件 emitter.off('foo') // unlisten // 取消所有事件 emitter.all.clear()
而我們如果在Vue3 + TypeScript 環境中使用的話,就需要型別化事件的型別,已達到強型別的處理目的,
import mitt from "mitt"; type Events = { foo: string; bar: number; }; // 提供泛型引數讓 emitter 能自動推斷引數型別 const emitter = mitt<Events>(); // 'e' 被推斷為string型別 emitter.on("foo", (e) => { console.log(e); }); // ts error: 型別 string 的引數不能賦值給型別 'number' 的引數 emitter.emit("bar", "xx"); // ts error: otherEvent 不存在與 Events 的key中 emitter.on("otherEvent", () => { // });
在前端專案使用的時候,我們在utils/mitt.ts中定義默認匯出的mitt物件,如下代碼所示,
// utils/mitt.ts import mitt, { Emitter } from 'mitt'; // 型別 const emitter: Emitter<MittType> = mitt<MittType>(); // 匯出 export default emitter;
在其中的MittType型別,可以單獨檔案放置TypeScript的預定義檔案目錄中,如types/mitt.d.ts
而我們在使用的時候,直接匯入該物件就可以了,如下代碼所示,
declare type MittType<T = any> = { openSetingsDrawer?: string; restoreDefault?: string; setSendColumnsChildren: T; .................. //省略其他事件型別 noticeRead: number; // 訊息已讀事件 lastAddParentId?: string | number;//新增記住最后的父資訊 };
例如我們定義一個更新和記住父選單的Mitt 事件,在頁面加載完畢的時候監聽事件,在頁面退出的時候關閉事件即可,如下代碼所示是在選單串列頁面中處理的,
<script lang="ts" setup name="sysMenu"> import { onMounted, onUnmounted, reactive, ref } from 'vue'; import mittBus from '/@/utils/mitt'; ...... onMounted(async () => { handleQuery(); mittBus.on('submitRefresh', () => { handleQuery(); }); mittBus.on('lastAddParentId', (pid) => { state.lastAddParentId = pid as string;//記住最后的父選單ID }); }); onUnmounted(() => { mittBus.off('submitRefresh'); mittBus.off('lastAddParentId'); }); </script>
在新增選單的時候我們觸發對應重繪事件 submitRefresh,以及觸發選擇的父記錄ID的事件 lastAddParentId,這樣就可以做相應的處理了,
例如在選單的編輯子控制元件頁面中,我們觸發對應的事件邏輯代碼如下所示,
// 關閉彈窗 const closeDialog = () => { mittBus.emit('submitRefresh'); state.isShowDialog = false; }; // 提交 const submit = () => { ruleFormRef.value.validate(async (valid: boolean) => { if (!valid) return; if (state.ruleForm.id != undefined && state.ruleForm.id > 0) { await menuApi.update(state.ruleForm); } else { await menuApi.add(state.ruleForm); //記住最后的選單 mittBus.emit('lastAddParentId', state.ruleForm.pid); } closeDialog(); }); };
如果為了減少每次重復的匯入mitt,也可以把它全域掛載到變數中,統一入口進行訪問,詳細可以參考隨筆《在基于vue-next-admin的Vue3+TypeScript前端專案中,為了使用方便全域掛載的物件介面》處理即可,
const $u: $u_interface = { message, test, util, date, crypto, base64, $t: i18n.global.t, fun: commonFunction(), cloneDeep, debounce, throttle, mitt }; //安裝$u組件到app上 import type { App } from 'vue'; export default { install(app: App<Element>) { // 掛載全域 app.config.globalProperties.$u = $u; } };

專注于代碼生成工具、.Net/.NetCore 框架架構及軟體開發,以及各種Vue.js的前端技術應用,著有Winform開發框架/混合式開發框架、微信開發框架、Bootstrap開發框架、ABP開發框架、SqlSugar開發框架等框架產品, 轉載請注明出處:撰寫人:伍華聰 http://www.iqidi.com
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/547837.html
標籤:其他
