| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323 |
- /*
- * @Author: mojunshou 1637302775@qq.com
- * @Date: 2025-04-01 10:30:46
- * @LastEditors: mojunshou 1637302775@qq.com
- * @LastEditTime: 2025-04-01 11:14:44
- * @Description:
- */
- import { error, warn } from "cc";
- import { EventName } from "./EventName";
- /**
- * 装饰器预加载数据
- */
- interface PreloadData {
- /** 事件名 */
- event: EventName;
- /** 事件回调函数名 */
- funcName: string;
- /** 事件是否只会触发一次 */
- once: boolean;
- }
- /**
- * 监听器
- */
- interface Listener {
- /** 回调 */
- cb: (...args: unknown[]) => void;
- /** 是否只触发一次 */
- once: boolean;
- }
- //#region 装饰器
- /**
- * 重写类方法
- * @param constructor 构造函数
- * @param onKey 在该方法内部调用Events.targetOn
- * @param offKey 在该方法内部调用Events.targetOff
- * @param onSuper 是否注册父类成员方法上绑定的事件,默认true
- */
- function rewrite(constructor: any, onKey: string, offKey: string, onSuper: boolean = true): void {
- let onFunc = constructor.prototype[onKey];
- let offFunc = constructor.prototype[offKey];
- constructor.prototype[onKey] = function () {
- Events.targetOn(this, onSuper);
- onFunc && onFunc.call(this);
- }
- constructor.prototype[offKey] = function () {
- Events.targetOff(this);
- offFunc && offFunc.call(this);
- }
- }
- /**
- * 类装饰器。用于覆盖onLoad和onDestroy方法,在onLoad中注册preloadEvent绑定的所有事件,在onDestroy注销绑定的所有事件
- * @param onSuper 是否注册父类成员方法上绑定的事件,默认true
- */
- export function eventsOnLoad(onSuper: boolean = true): (constructor: any) => void {
- return function (constructor: any) {
- rewrite(constructor, "onLoad", "onDestroy", onSuper);
- };
- }
- /**
- * 类装饰器。用于覆盖onEnable和onDisable方法,在onEnable中注册preloadEvent绑定的所有事件,在onDisable注销绑定的所有事件
- * @param onSuper 是否注册父类成员方法上绑定的事件,默认true
- */
- export function eventsOnEnable(onSuper: boolean = true): (constructor: any) => void {
- return function (constructor: any) {
- rewrite(constructor, "onEnable", "onDisable", onSuper);
- };
- }
- /**
- * 非静态成员方法装饰器。用于预先载入待注册的事件,配合eventsOnLoad、eventsOnEnable、targetOn使用
- * @param event 事件名
- * @param once 事件是否只会触发一次,默认false
- */
- export function preloadEvent(event: EventName, once: boolean = false): (target: any, funcName: string, desc: PropertyDescriptor) => void {
- return function (target: any, funcName: string, desc: PropertyDescriptor) {
- let arr = Events.classMap.get(target.constructor);
- if (arr === undefined) {
- arr = [];
- Events.classMap.set(target.constructor, arr);
- } else {
- let find = arr.find((e) => {
- return e.event === event && e.funcName === funcName;
- });
- if (find) {
- error(`event: ${EventName[event]} 重复载入`);
- return;
- }
- }
- arr.push({
- event: event,
- funcName: funcName,
- once: once
- });
- };
- }
- //#endregion
- /**
- * 事件收发管理类
- */
- export default class Events {
- /**
- * 预加载数据,存储构造函数、监听事件、监听函数名,用于实例化时注册事件
- */
- public static classMap: Map<Function, PreloadData[]> = new Map();
- /**
- * 存储监听事件、监听函数与监听对象
- */
- private static _eventsMap: Map<EventName, Map<Object, Listener[]>> = new Map();
- /**
- * 注册与target构造函数预先绑定的所有事件
- * @param target 注册目标
- * @param onSuper 是否注册父类成员方法上绑定的事件,默认true
- */
- public static targetOn(target: Object, onSuper: boolean = true): void {
- if (onSuper) {
- this.classMap.forEach((value: PreloadData[], key: Function) => {
- if (target instanceof key) {
- for (let i = 0; i < value.length; i++) {
- let e = value[i];
- this.on(e.event, target[e.funcName], target, e.once);
- }
- }
- });
- } else {
- let arr = this.classMap.get(target.constructor);
- if (arr) {
- for (let i = 0; i < arr.length; i++) {
- let e = arr[i];
- this.on(e.event, target[e.funcName], target, e.once);
- }
- }
- }
- }
- /**
- * 注册事件
- * @param event 事件名
- * @param cb 处理事件的监听函数
- * @param target 注册目标
- * @param once 事件是否只会触发一次,默认false
- */
- public static on(event: EventName, cb: (...args: any[]) => void, target: Object, once: boolean = false): void {
- if (!cb || !target) {
- error(`event: ${EventName[event]} listener或target不能为空`);
- return;
- }
- let map: Map<Object, Listener[]> = this._eventsMap.get(event);
- let list: Listener[] = [];
- if (map === undefined) {
- map = new Map();
- map.set(target, list);
- this._eventsMap.set(event, map);
- } else {
- list = map.get(target);
- if (list === undefined) {
- list = [];
- map.set(target, list);
- } else {
- let result = list.find((e) => { return e.cb === cb; });
- if (result) {
- error(`event: ${EventName[event]} 重复注册`);
- return;
- }
- }
- }
- let listener: Listener = {
- cb: cb,
- once: once
- };
- list.push(listener);
- }
- /**
- * 注册事件,触发一次后自动注销
- * @param event 事件名
- * @param cb 处理事件的监听函数
- * @param target 注册目标
- */
- public static once(event: EventName, cb: (...args: any[]) => void, target: Object): void {
- this.on(event, cb, target, true);
- }
- /**
- * 移除事件
- * @param event 事件名
- * @param cb 处理事件的监听函数
- * @param target 注册目标
- */
- public static off(event: EventName, cb: (...args: any[]) => void, target: Object): void {
- if (!cb || !target) {
- error(`event: ${EventName[event]} listener或target不能为空`);
- return;
- }
- let map: Map<Object, Listener[]> = this._eventsMap.get(event);
- if (map === undefined) {
- error(`event: ${EventName[event]} 未注册该事件`);
- return;
- }
- let list: Listener[] = map.get(target);
- if (list === undefined) {
- error(`event: ${EventName[event]} target上未注册该事件`);
- return;
- }
- let index = list.findIndex((e) => { return e.cb === cb; });
- if (index < 0) {
- error(`event: ${EventName[event]} target上未以该listener注册该事件`);
- return;
- }
- list.splice(index, 1);
- if (list.length <= 0) {
- map.delete(target);
- map.size <= 0 && this._eventsMap.delete(event);
- }
- }
- /**
- * 移除target上注册的所有事件
- * @param target 注册目标
- */
- public static targetOff(target: Object): void {
- if (!target) {
- error(`event: ${target} target不能为空`);
- return;
- }
- this._eventsMap.forEach((map, event) => {
- map.delete(target);
- map.size <= 0 && this._eventsMap.delete(event);
- });
- }
- /**
- * 派发事件
- * @param event 事件名
- * @param args 事件参数
- */
- public static emit(event: EventName, ...args: unknown[]): void {
- let map: Map<Object, Listener[]> = this._eventsMap.get(event);
- if (map === undefined) {
- warn(`event: ${EventName[event]} 未注册该事件`);
- return;
- }
- let i: number;
- let callArr: Array<{ cb: (...args: unknown[]) => void; target: Object }> = [];
- let onceArr: Array<{ cb: (...args: unknown[]) => void; target: Object }> = [];
- map.forEach((list, target) => {
- for (i = 0; i < list.length; i++) {
- let listener = list[i];
- callArr.push({ cb: listener.cb, target: target });
- if (listener.once) {
- onceArr.push({ cb: listener.cb, target: target });
- }
- }
- });
- // 移除所有once的监听
- for (i = 0; i < onceArr.length; i++) {
- let e = onceArr[i];
- this.off(event, e.cb, e.target);
- }
- // 延迟到此处调用事件回调,防止受到回调过程中的 注册/注销 影响
- for (i = 0; i < callArr.length; i++) {
- let e = callArr[i];
- e.cb.apply(e.target, args);
- }
- }
- /**
- * 派发事件--异步
- * @param event 事件名
- * @param args 事件参数
- */
- public static async emitAsync(event: EventName, ...args: unknown[]): Promise<void> {
- let map: Map<Object, Listener[]> = this._eventsMap.get(event);
- if (map === undefined) {
- warn(`event: ${EventName[event]} 未注册该事件`);
- return;
- }
- let i: number;
- let callArr: Array<{ cb: (...args: unknown[]) => void; target: Object }> = [];
- let onceArr: Array<{ cb: (...args: unknown[]) => void; target: Object }> = [];
- map.forEach((list, target) => {
- for (i = 0; i < list.length; i++) {
- let listener = list[i];
- callArr.push({ cb: listener.cb, target: target });
- if (listener.once) {
- onceArr.push({ cb: listener.cb, target: target });
- }
- }
- });
- // 移除所有once的监听
- for (i = 0; i < onceArr.length; i++) {
- let e = onceArr[i];
- this.off(event, e.cb, e.target);
- }
- // 延迟到此处调用事件回调,防止受到回调过程中的 注册/注销 影响
- let arr: Promise<unknown>[] = [];
- for (i = 0; i < callArr.length; i++) {
- let e = callArr[i];
- arr.push(e.cb.apply(e.target, args));
- }
- await Promise.all(arr);
- }
- }
|