发布订阅模式(TS)
源码:
class EventBus{
event:Record<string,Set<(...args:Array<any>)=>void>> = {}
on(eventName:string,cb:(...args:Array<any>)=>void){
( this.event[eventName] ??= new Set()).add(cb)
}
emit(eventName:string,...args:Array<any>){
this.event[eventName].forEach(cb=>cb(...args as Array<any>))
}
off(eventName:string,cb:(...args:Array<any>)=>void){
this.event[eventName].delete(cb)
}
once(eventName:string,cb:(...args:Array<any>)=>void){
const handler = (...args:Array<any>)=>{
cb(...args)
this.off(eventName,handler)
}
this.on(eventName,handler)
}
}
export const bus = new EventBus()
使用:
子组件:
<script setup lang="ts">
import { ref, watchEffect } from 'vue'
import { bus } from '../../event';
const count = ref(0)
const addCount = (val:number)=>{count.value+=val}
bus.on('addCount', addCount)
watchEffect(()=>{
if(count.value >10){
bus.off('addCount',addCount)
}
})
</script>
<template>
<div>
<div>{{ count }}</div>
</div>
</template>
<style scoped>
.read-the-docs {
color: #888;
}
</style>
父组件:
<script setup lang="ts">
import { bus } from '../event';
import child from './test/child.vue';
function addCount(){
bus.emit('addCount',2)
}
</script>
<template>
<div>
<child></child>
<button @click="addCount">Count++</button>
</div>
</template>
<style scoped>
.read-the-docs {
color: #888;
}
</style>