const EventEmitter = (function () {
const emitters = [];
const ONCE_SYMBOL = '$$EMITTER_ONCE';
class $EventEmitter{
constructor(isInit) {
emitters.push(this);
this.listenrs = {};
if (isInit) {
return Object.assign(this, {
create() {
return new $EventEmitter();
},
});
}
}
isFn(fn) {
return fn instanceof Function;
}
once(evtName, fn) {
/* 思路一:新开一个数组备份 */
/* 思路二:fn添加属性 */
fn[ONCE_SYMBOL] = ONCE_SYMBOL;
this.on(evtName, fn);
}
clearOnce(evtName) {
const cbs = this.listenrs[evtName];
for (let i = 0; i < cbs.length; i++) {
if (cbs[i][ONCE_SYMBOL] === ONCE_SYMBOL) {
cbs.splice(i, 1);
i--;
}
}
}
on(evtName, fn) {
if (!this.isFn(fn)) return;
if (this.listenrs[evtName]) {
this.listenrs[evtName].push(fn);
} else {
this.listenrs[evtName] = [fn];
}
}
off(evtName, fn) {
if (fn && this.listenrs[evtName]) {
let index = this.listenrs[evtName].findIndex(cb => cb === fn);
if (index >= 0) {
this.listenrs[evtName].splice(index, 1);
}
} else {
delete this.listenrs[evtName];
}
}
emit(evtName, root) {
// 调试信息
if (root && this === EventEmitter) return console.log('%cEventEmitter已是ROOT', 'color:red;');
/* root 优先触发 */
if (root && this !== EventEmitter) {
EventEmitter.emit(evtName);
}
if (this.listenrs[evtName]) {
this.listenrs[evtName].forEach(cb => cb && cb());
/* 实现once */
this.clearOnce(evtName);
}
}
/* 任何一个emitter可以触发 */
emitAll(evtName) {
emitters.forEach(emitter => {
emitter.emit(evtName);
});
}
}
/* 对外暴露,class内部作为root使用 */
const EventEmitter = new $EventEmitter(true);
return EventEmitter;
})();
EventEmitter.on('haha', function () {
console.log('你好');
});
EventEmitter.on('haha', function () {
console.log('你好2');
});
EventEmitter.on('root-haha', function () {
console.log('哈哈,emit by child');
});
setTimeout(() => {
EventEmitter.emit('haha');
}, 2000);
const bus1 = EventEmitter.create();
bus1.on('haha', function () {
console.log('你好');
});
bus1.on('root-haha', function () {
console.log('root-哈哈');
});
bus1.once('haha', function () {
console.log('once');
});
bus1.once('haha', function () {
console.log('once1');
});
bus1.once('haha', function () {
console.log('once2');
});
setTimeout(() => {
bus1.emit('haha');
EventEmitter.emit('root-haha', true); // 无效
bus1.emit('root-haha', true);
}, 2000);
const bus3 = EventEmitter.create();
setTimeout(() => {
console.log('%c全部触发', 'color:red;');
bus3.emitAll('haha')
}, 4000);