心血来潮,想要手写实现一个类似pubsub-js或者vue中央事件总线的发布订阅的小类库
代码如下:
新建一个文件 JasonMa_PubSub.js
const JasonMa_PubSub = {
//存储事件及方法
listenStore: {},
//订阅/监听
on: function(method, cb) {
//如果已监听过这个方法,就push这个回调函数;如果没监听就创建键值对,值为一个数组用于存储当前回调函数
if (this.listenStore[method]) {
this.listenStore[method].push(cb);
} else {
this.listenStore[method] = [cb];
}
},
//发布/触发
emit: function(method, ...args) {
//获取到监听方法对应的回调函数数组,逐个触发
const fnList = this.listenStore[method];
if (!fnList || fnList.length === 0) {
return false;
} else {
fnList.forEach(cb => {
cb.apply(this, args);
});
}
},
//关闭订阅
off: function(method) {
const fnList = this.listenStore[method];
if (fnList && fnList.length !== 0) {
delete this.listenStore[method];
}
},
//只订阅一次
once: function(method, cb) {
let onceFn = (...args) => {
cb.apply(this, args); //执行发布
this.off(method); //停止订阅
};
this.on(method, onceFn); //注册重构后的一次监听事件
}
};
export default JasonMa_PubSub;
//es6引入
import pubsub from './JasonMa_PubSub.js'
//监听abc事件
pubsub.on("abc", function(...args) {
console.log("abc触发了", args);
});
//监听aaaaa事件,预期仅触发一次
pubsub.once("aaaaa", function(...args) {
console.log("aaaaa触发了", args);
});
//每过1.5秒触发abc aaaaa事件
setInterval(() => {
pubsub.emit("abc", 1, 2, 3, 4);
pubsub.emit("aaaaa", "我是aaaaa的数据");
}, 1500);
//5秒后关闭abc事件监听
setTimeout(() => {
pubsub.off("abc");
}, 5000);
结果:
aaaaa 只会触发一次
abc 只会触发3次,之后不再触发