/** ***************************************** * Created by edonet@163.com * Created on 2021-03-25 00:03:38 ***************************************** */ 'use strict'; /** ***************************************** * 事件处理函数 ***************************************** */ type Handler = (...args: any[]) => void; /** ***************************************** * 事件对象 ***************************************** */ interface Event { type: string; once: boolean; handler: Handler; } /** ***************************************** * 内置接口 ***************************************** */ export interface EventEmitter { on(type: '$on', handler: (event: Event) => void): this; on(type: '$off', handler: (event: { type?: string, handler?: Handler }) => void): this; on(type: '$emit', handler: (event: { type: string, args: unknown[] }) => void): this; once(type: '$on', handler: (event: Event) => void): this; once(type: '$off', handler: (event: { type?: string, handler?: Handler }) => void): this; once(type: '$emit', handler: (event: { type: string, args: unknown[] }) => void): this; } /** ***************************************** * 事件派发器 ***************************************** */ export class EventEmitter { /** 事件集 */ private $$events!: Record; /** 初始化对象 */ constructor() { Object.defineProperty(this, '$$events', { configurable: false, enumerable: false, writable: true, value: {}, }); } /** 添加事件 */ public on(type: string, handler: Handler): this { // 校验类型 if (!type || typeof type !== 'string') { throw new Error('expect `type` to be a valid string!'); } // 校验函数 if (typeof handler !== 'function') { throw new Error('expect `handler` to be a function!'); } // 定义事件 const event = { type, once: false, handler }; // 派发内部通知 if (!['$on', '$once', '$off', '$emit'].includes(type)) { this.emit('$on', event); } // 获取事件列表 const list = this.$$events[type]; // 添加事件 if (list) { list.push(event); } else { this.$$events[type] = [event]; } // 返回自身 return this; } /** 添加一次性事件 */ public once(type: string, handler: Handler): this { // 校验类型 if (!type || typeof type !== 'string') { throw new Error('expect `type` to be a valid string!'); } // 校验函数 if (typeof handler !== 'function') { throw new Error('expect `handler` to be a function!'); } // 定义事件 const event = { type, once: true, handler }; // 派发内部通知 if (!['$on', '$once', '$off', '$emit'].includes(type)) { this.emit('$on', event); } // 获取事件列表 const list = this.$$events[type]; // 添加事件 if (list) { list.push(event); } else { this.$$events[type] = [event]; } // 返回自身 return this; } /** 移除事件 */ public off(type?: string, handler?: Handler): this { // 移除指定事件 if (typeof handler === 'function') { // 校验类型 if (!type || typeof type !== 'string') { throw new Error('expect `type` to be a valid string!'); } // 获取事件列表 const list = this.$$events[type] || []; // 存在事件列表 if (list && list.length) { const idx = list.findIndex(event => event.handler === handler); // 存在事件 if (idx > -1) { // 派发内部通知 if (!['$on', '$once', '$off', '$emit'].includes(type)) { this.emit('$off', { type, handler }); } // 执行移除 idx ? list.splice(idx, 1) : list.shift(); } } // 返回自身 return this; } // 校验函数 if (typeof handler !== 'undefined') { throw new Error('expect `handler` to be a function!'); } // 移除事件列表 if (type && typeof type === 'string') { // 派发内部通知 if (!['$on', '$once', '$off', '$emit'].includes(type)) { this.emit('$off', { type }); } // 清空事件列表 this.$$events[type] = []; // 返回自身 return this; } // 校验类型 if (typeof type !== 'undefined') { throw new Error('expect `type` to be a valid string!'); } // 派发内部通知 this.emit('$off', {}); // 清空事件集 this.$$events = Object.create(null); // 返回自身 return this; } /** 移除事件 */ public emit(type: string, ...args: unknown[]): this { // 校验类型 if (!type || typeof type !== 'string') { throw new Error('expect `type` to be a valid string!'); } // 派发内部通知 if (!['$on', '$once', '$off', '$emit'].includes(type)) { this.emit('$emit', { type, args }); } // 获取事件列表 let list = this.$$events[type]; // 不存在事件 if (!list || !list.length) { return this; } // 重置事件列表 this.$$events[type] = list.filter(event => !event.once); // 执行列表 list.filter(event => event.handler.apply(this, args)); // 返回自身 return this; } }