Events.ts 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. /*
  2. * @Author: mojunshou 1637302775@qq.com
  3. * @Date: 2025-04-01 10:30:46
  4. * @LastEditors: mojunshou 1637302775@qq.com
  5. * @LastEditTime: 2025-04-01 11:14:44
  6. * @Description:
  7. */
  8. import { error, warn } from "cc";
  9. import { EventName } from "./EventName";
  10. /**
  11. * 装饰器预加载数据
  12. */
  13. interface PreloadData {
  14. /** 事件名 */
  15. event: EventName;
  16. /** 事件回调函数名 */
  17. funcName: string;
  18. /** 事件是否只会触发一次 */
  19. once: boolean;
  20. }
  21. /**
  22. * 监听器
  23. */
  24. interface Listener {
  25. /** 回调 */
  26. cb: (...args: unknown[]) => void;
  27. /** 是否只触发一次 */
  28. once: boolean;
  29. }
  30. //#region 装饰器
  31. /**
  32. * 重写类方法
  33. * @param constructor 构造函数
  34. * @param onKey 在该方法内部调用Events.targetOn
  35. * @param offKey 在该方法内部调用Events.targetOff
  36. * @param onSuper 是否注册父类成员方法上绑定的事件,默认true
  37. */
  38. function rewrite(constructor: any, onKey: string, offKey: string, onSuper: boolean = true): void {
  39. let onFunc = constructor.prototype[onKey];
  40. let offFunc = constructor.prototype[offKey];
  41. constructor.prototype[onKey] = function () {
  42. Events.targetOn(this, onSuper);
  43. onFunc && onFunc.call(this);
  44. }
  45. constructor.prototype[offKey] = function () {
  46. Events.targetOff(this);
  47. offFunc && offFunc.call(this);
  48. }
  49. }
  50. /**
  51. * 类装饰器。用于覆盖onLoad和onDestroy方法,在onLoad中注册preloadEvent绑定的所有事件,在onDestroy注销绑定的所有事件
  52. * @param onSuper 是否注册父类成员方法上绑定的事件,默认true
  53. */
  54. export function eventsOnLoad(onSuper: boolean = true): (constructor: any) => void {
  55. return function (constructor: any) {
  56. rewrite(constructor, "onLoad", "onDestroy", onSuper);
  57. };
  58. }
  59. /**
  60. * 类装饰器。用于覆盖onEnable和onDisable方法,在onEnable中注册preloadEvent绑定的所有事件,在onDisable注销绑定的所有事件
  61. * @param onSuper 是否注册父类成员方法上绑定的事件,默认true
  62. */
  63. export function eventsOnEnable(onSuper: boolean = true): (constructor: any) => void {
  64. return function (constructor: any) {
  65. rewrite(constructor, "onEnable", "onDisable", onSuper);
  66. };
  67. }
  68. /**
  69. * 非静态成员方法装饰器。用于预先载入待注册的事件,配合eventsOnLoad、eventsOnEnable、targetOn使用
  70. * @param event 事件名
  71. * @param once 事件是否只会触发一次,默认false
  72. */
  73. export function preloadEvent(event: EventName, once: boolean = false): (target: any, funcName: string, desc: PropertyDescriptor) => void {
  74. return function (target: any, funcName: string, desc: PropertyDescriptor) {
  75. let arr = Events.classMap.get(target.constructor);
  76. if (arr === undefined) {
  77. arr = [];
  78. Events.classMap.set(target.constructor, arr);
  79. } else {
  80. let find = arr.find((e) => {
  81. return e.event === event && e.funcName === funcName;
  82. });
  83. if (find) {
  84. error(`event: ${EventName[event]} 重复载入`);
  85. return;
  86. }
  87. }
  88. arr.push({
  89. event: event,
  90. funcName: funcName,
  91. once: once
  92. });
  93. };
  94. }
  95. //#endregion
  96. /**
  97. * 事件收发管理类
  98. */
  99. export default class Events {
  100. /**
  101. * 预加载数据,存储构造函数、监听事件、监听函数名,用于实例化时注册事件
  102. */
  103. public static classMap: Map<Function, PreloadData[]> = new Map();
  104. /**
  105. * 存储监听事件、监听函数与监听对象
  106. */
  107. private static _eventsMap: Map<EventName, Map<Object, Listener[]>> = new Map();
  108. /**
  109. * 注册与target构造函数预先绑定的所有事件
  110. * @param target 注册目标
  111. * @param onSuper 是否注册父类成员方法上绑定的事件,默认true
  112. */
  113. public static targetOn(target: Object, onSuper: boolean = true): void {
  114. if (onSuper) {
  115. this.classMap.forEach((value: PreloadData[], key: Function) => {
  116. if (target instanceof key) {
  117. for (let i = 0; i < value.length; i++) {
  118. let e = value[i];
  119. this.on(e.event, target[e.funcName], target, e.once);
  120. }
  121. }
  122. });
  123. } else {
  124. let arr = this.classMap.get(target.constructor);
  125. if (arr) {
  126. for (let i = 0; i < arr.length; i++) {
  127. let e = arr[i];
  128. this.on(e.event, target[e.funcName], target, e.once);
  129. }
  130. }
  131. }
  132. }
  133. /**
  134. * 注册事件
  135. * @param event 事件名
  136. * @param cb 处理事件的监听函数
  137. * @param target 注册目标
  138. * @param once 事件是否只会触发一次,默认false
  139. */
  140. public static on(event: EventName, cb: (...args: any[]) => void, target: Object, once: boolean = false): void {
  141. if (!cb || !target) {
  142. error(`event: ${EventName[event]} listener或target不能为空`);
  143. return;
  144. }
  145. let map: Map<Object, Listener[]> = this._eventsMap.get(event);
  146. let list: Listener[] = [];
  147. if (map === undefined) {
  148. map = new Map();
  149. map.set(target, list);
  150. this._eventsMap.set(event, map);
  151. } else {
  152. list = map.get(target);
  153. if (list === undefined) {
  154. list = [];
  155. map.set(target, list);
  156. } else {
  157. let result = list.find((e) => { return e.cb === cb; });
  158. if (result) {
  159. error(`event: ${EventName[event]} 重复注册`);
  160. return;
  161. }
  162. }
  163. }
  164. let listener: Listener = {
  165. cb: cb,
  166. once: once
  167. };
  168. list.push(listener);
  169. }
  170. /**
  171. * 注册事件,触发一次后自动注销
  172. * @param event 事件名
  173. * @param cb 处理事件的监听函数
  174. * @param target 注册目标
  175. */
  176. public static once(event: EventName, cb: (...args: any[]) => void, target: Object): void {
  177. this.on(event, cb, target, true);
  178. }
  179. /**
  180. * 移除事件
  181. * @param event 事件名
  182. * @param cb 处理事件的监听函数
  183. * @param target 注册目标
  184. */
  185. public static off(event: EventName, cb: (...args: any[]) => void, target: Object): void {
  186. if (!cb || !target) {
  187. error(`event: ${EventName[event]} listener或target不能为空`);
  188. return;
  189. }
  190. let map: Map<Object, Listener[]> = this._eventsMap.get(event);
  191. if (map === undefined) {
  192. error(`event: ${EventName[event]} 未注册该事件`);
  193. return;
  194. }
  195. let list: Listener[] = map.get(target);
  196. if (list === undefined) {
  197. error(`event: ${EventName[event]} target上未注册该事件`);
  198. return;
  199. }
  200. let index = list.findIndex((e) => { return e.cb === cb; });
  201. if (index < 0) {
  202. error(`event: ${EventName[event]} target上未以该listener注册该事件`);
  203. return;
  204. }
  205. list.splice(index, 1);
  206. if (list.length <= 0) {
  207. map.delete(target);
  208. map.size <= 0 && this._eventsMap.delete(event);
  209. }
  210. }
  211. /**
  212. * 移除target上注册的所有事件
  213. * @param target 注册目标
  214. */
  215. public static targetOff(target: Object): void {
  216. if (!target) {
  217. error(`event: ${target} target不能为空`);
  218. return;
  219. }
  220. this._eventsMap.forEach((map, event) => {
  221. map.delete(target);
  222. map.size <= 0 && this._eventsMap.delete(event);
  223. });
  224. }
  225. /**
  226. * 派发事件
  227. * @param event 事件名
  228. * @param args 事件参数
  229. */
  230. public static emit(event: EventName, ...args: unknown[]): void {
  231. let map: Map<Object, Listener[]> = this._eventsMap.get(event);
  232. if (map === undefined) {
  233. warn(`event: ${EventName[event]} 未注册该事件`);
  234. return;
  235. }
  236. let i: number;
  237. let callArr: Array<{ cb: (...args: unknown[]) => void; target: Object }> = [];
  238. let onceArr: Array<{ cb: (...args: unknown[]) => void; target: Object }> = [];
  239. map.forEach((list, target) => {
  240. for (i = 0; i < list.length; i++) {
  241. let listener = list[i];
  242. callArr.push({ cb: listener.cb, target: target });
  243. if (listener.once) {
  244. onceArr.push({ cb: listener.cb, target: target });
  245. }
  246. }
  247. });
  248. // 移除所有once的监听
  249. for (i = 0; i < onceArr.length; i++) {
  250. let e = onceArr[i];
  251. this.off(event, e.cb, e.target);
  252. }
  253. // 延迟到此处调用事件回调,防止受到回调过程中的 注册/注销 影响
  254. for (i = 0; i < callArr.length; i++) {
  255. let e = callArr[i];
  256. e.cb.apply(e.target, args);
  257. }
  258. }
  259. /**
  260. * 派发事件--异步
  261. * @param event 事件名
  262. * @param args 事件参数
  263. */
  264. public static async emitAsync(event: EventName, ...args: unknown[]): Promise<void> {
  265. let map: Map<Object, Listener[]> = this._eventsMap.get(event);
  266. if (map === undefined) {
  267. warn(`event: ${EventName[event]} 未注册该事件`);
  268. return;
  269. }
  270. let i: number;
  271. let callArr: Array<{ cb: (...args: unknown[]) => void; target: Object }> = [];
  272. let onceArr: Array<{ cb: (...args: unknown[]) => void; target: Object }> = [];
  273. map.forEach((list, target) => {
  274. for (i = 0; i < list.length; i++) {
  275. let listener = list[i];
  276. callArr.push({ cb: listener.cb, target: target });
  277. if (listener.once) {
  278. onceArr.push({ cb: listener.cb, target: target });
  279. }
  280. }
  281. });
  282. // 移除所有once的监听
  283. for (i = 0; i < onceArr.length; i++) {
  284. let e = onceArr[i];
  285. this.off(event, e.cb, e.target);
  286. }
  287. // 延迟到此处调用事件回调,防止受到回调过程中的 注册/注销 影响
  288. let arr: Promise<unknown>[] = [];
  289. for (i = 0; i < callArr.length; i++) {
  290. let e = callArr[i];
  291. arr.push(e.cb.apply(e.target, args));
  292. }
  293. await Promise.all(arr);
  294. }
  295. }