一些集成的就比较简单就不介绍了,直接看单测
import { EventBus } from "../plugin/EventBus";
const bus = new EventBus();
describe("实现:事件车(发布订阅模式)", () => {
it("event bus on", () => {
const muckFn = jest.fn();
bus.on("event one", muckFn);
expect(bus.eventsMap.size).toBe(1)
});
// 事件监听 on这个功能 使用muck一个fn 看bus.eventMap这个集合中的 数量 是否放入中了
it("event bus emit", () => {
const muckFn = jest.fn();
bus.on("event one", muckFn);
bus.emit("event one", '1111111111111111111');
bus.emit("event one", '2222222222222222222');
bus.emit("event one", '3333333333333333333');
expect(muckFn).toBeCalledTimes(3)
});
// 发送事件 看muck的fn调用次数 是不是三次
it("event bus off", () => {
const muckFn = jest.fn();
bus.on("event one", muckFn);
bus.emit("event one", '1111111111111111111');
bus.off("event one", muckFn);
bus.emit("event one", '1111111111111111111');
expect(muckFn).toBeCalledTimes(1)
});
// 主要是看off之后是否函数继续调用
it("event bus once", () => {
const muckFn = jest.fn();
bus.once("event once", muckFn);
bus.emit("event once", '1111111111111111111');
bus.emit("event once", '1111111111111111111');
bus.emit("event once", '1111111111111111111');
bus.emit("event once", '1111111111111111111');
expect(muckFn).toBeCalledTimes(1)
});
// 主要是看once创建的是否会接收多次
});
现在开始具体实现逻辑。
首先将任务拆分:
1、实现on是要将传入的函数和事件名存储到一个数据容器中,我选择的是Set()。
2、现在先写一个类,并先要声明存储的数据容器
export class EventBus {
constructor() {
this.eventsMap = new Set();
}
}
3、on实现:就是将这里的内容存储到容器中
on(eveName, cb) {
this.eventsMap.add({
eveName,
callback: cb,
});
}
4、emit实现:在调用时寻找容器中时间名和传入的事件名相等的项,调用函数,并将参数传入
emit(eveName, ...args) {
const eventSet = this.eventsMap;
for (const item of eventSet) {
if (item.eveName == eveName) {
item.callback(...args);
if (item.once) {
eventSet.delete(item);
}
}
}
}
5、once实现:与on相似只是使用了一个属性标识只执行一次。
once(eveName, cb) {
this.eventsMap.add({
eveName,
callback: cb,
once: true,
});
}
6、off实现:就是在调用时在容器寻找与传入事件名相同的项,并删除。
off(eveName) {
const eventSet = this.eventsMap;
for (const item of eventSet) {
if (item.eveName == eveName) {
this.eventsMap.delete(item);
}
}
}
最后的单侧结果:
7、将插件集成到vue3中:
export default {
install(app) {
// 挂载到原型 app.config.globalProperties 方式
const eventBus = new EventBus();
app.config.globalProperties.$bus = eventBus;
},
};
8、在main.js使用use进行注册:
import { createApp } from "vue";
import mountEventBus from "./plugin/EventBus";
import App from "./App.vue";
const app = createApp(App);
app.use(mountEventBus).mount("#app");
9、在vue3的组件内使用:
<template>
<div>
<HelloWorld></HelloWorld>
</div>
</template>
<script>
import { getCurrentInstance } from 'vue'
import HelloWorld from './components/HelloWorld.vue';
export default {
components: { HelloWorld },
setup() {
const { proxy } = getCurrentInstance()
proxy.$bus.on('hahha', (...args) => {
console.log(...args);
})
return {
}
}
}
</script>