vue3.0通讯 - hook优雅的封装mitt.js
简单的说 mitt 就是一个全局的总线程,在 vue2.0中,我们经常会使用EventBus去处理问题,这时候你会说啥是总线程呢。更简单的说,其实就是发布订阅事件。
·
mitt 是什么
简单的说 mitt 就是一个全局的总线程,在 vue2.0中,我们经常会使用EventBus去处理问题,这时候你会说啥是总线程呢。更简单的说,其实就是发布订阅事件。
EventBus的简易源码
class Bus {
constructor() {
this.callback = {};
}
/**
* @description: 发布事件
* @param {*} name 名称
* @param {*} fn 方法
*/
$on(name, fn) {
this.callback[name] = this.callback[name] || [];
this.callback[name].push(fn);
}
/**
* @description: 订阅器-接收器
* @param {*} name 方法的名称
* @param {*} args 入参
*/
$emit(name, args) {
if (this.callback[name]) {
this.callback[name].forEach((cb) => {
cb(args);
});
}
}
}
// 挂载在 vue 的原型上
Vue.prototype.$bus = new Bus();
miit的使用
安装
npm install --save mitt
通常的使用
import mitt from 'mitt'
const emitter = mitt()
const TOPIC = 'topic'
// 订阅
emitter.on(TOPIC, (data)=>{
console.log(data);
})
// 发布事件
emitter.emit(TOPIC, { a: 'b' })
// 取消订阅
emitter.off(TOPIC, onFoo)
// 清空所有的事件
emitter.all.clear()
问题与痛点
命名问题
每一次都需要去思考不重名,一旦使用重名,将很难定位问题
销毁事件
事件都挂载到了总线程上,你需要思考如何去销毁掉订阅的事件,避免不必要的开销
为什么不去用 store去处理问题
所有的问题存在则是必然,可为什么是必然呢?做一个假设,你现在处理一个表格数据的刷新,你是希望把表格数据放在 store 中还是放在业务组件中吗?很显然业务组件中,可以让代码的逻辑更加要区分,而不是把所有的数据,一股脑的放入 store 处理,这样代码的单一职责原则才能更好的体现。
hook 封装
useEventbus.ts
import { onUnmounted } from 'vue'
import mitt from 'mitt'
type IUseEventbus = {
customEmit: (eventName: string) => void
customOn: (eventName: string, callback: () => void) => void
toRefreshTable: () => void
refreshTable: (callback: () => void) => void
}
const emitter: mitt.Emitter = mitt()
/**
* @description: 自定义触发器
* @param {*} eventName 名称
*/
const customEmit = (eventName: string) => {
emitter.emit(eventName)
}
/**
* @description: 自定义接收器
* @param {*} name 名称
* @param {*} callback 回调的函数
*/
const customOn = (eventName: string, callback: () => void) => {
emitter.on(eventName, () => callback())
}
/**
* @description: 通知刷新表格数据
*/
const toRefreshTable = () => {
emitter.emit('refreshTable')
}
/**
* @description: 刷新表格数据
* @param {*} callback 回调的函数
*/
const refreshTable = (callback: () => void) => {
emitter.on('refreshTable', () => callback())
}
/**
* @description: 导出useEventbus
*/
export const useEventbus = (): IUseEventbus => {
// 销毁的事件
onUnmounted(() => {
// 清空所有的事件,避免多组件互相清理
emitter.all.clear()
})
return {
customEmit,
customOn,
toRefreshTable,
refreshTable
}
}
main.vue - 主组件
<script lang="ts" setup>
import { onMounted } from 'vue';
import { useEventbus } from '@/hooks/useEventbus'
const eventbus = useEventbus()
onMounted(() => {
// 订阅 init 方法
eventbus.customOn('init', () => {
init()
})
})
const init = ()=>{
// http
}
</script>
release.vue - 发布通讯组件
<script lang="ts" setup>
import { useEventbus } from '@/hooks/useEventbus'
const eventbus = useEventbus()
const handleClick = () => {
// 发布通讯
eventbus.customEmit('init')
}
</script>
更多推荐
已为社区贡献1条内容
所有评论(0)