事件分发器你们怎么设计


//1、事件以对象形式发送;参数通过构造函数传递到内部;参数类型,参数数量都可以约束
eventDispatcher.dispatch(new XXXEvent(param1, param2))

//2、事件以字符串形式发送;额外可以传入不定参数;但是参数数量、参数类型没有约束;增加了出错的概率。
eventDispatcher.dispatch("xxeventtype", param1, param2)
eventDispatcher.dispatch(EventEnum.xxxtype, param1, param2)

你们自己的事件分发器一般用哪种形式?
第一种规范性,封装性更好,缺点是:一个简单的事件要定义一个事件类型很烦
第二种更自由,使用方便。缺点是:参数不受约束,不注意使用有可能出错。特别是多人合作的时候
有没有一种思路介意两者之间的:不用新的事件类型定义一个类,而且还有参数约束
你们都是用哪种?请回答 1、2;项目规模;

用2,项目模块上百,有老项目界面上600+的。

事件注册与派发最简单的观察者模式的运用。
ts自己写一个,几十行代码就够了。
当然用法还是你说的第二种
image

第二种,但是不用纯字符串,用枚举字符串EventType.SomeEvent,稍微约束一下。

可以看下马赛克的事件系统

1赞

我是用一个类的静态方法来做枚举GameEvent.XXXEvent

class GameEvent {
    XXXEvent(parm1: string, parm2: number) { }
    ...
}

然后这样做就可以约束参数

function emit<T extends (...args: any[]) => any, P extends Parameters<T>>(event: T, ...messages: P) { }

TypeScript 学起来

这是一种不错的思路 :+1:

不过比较通用的事件分发器都是以string作为事件类型的区分的。就算时new XXEvent()也是用的内部的字符串作为key。 你这种只能用方法的地址作为KEY

我选的是第二种,我觉得这样自由度更高,但是也有缺点,就是监听的时候还要去数据源去收集有哪些变量

如果是马赛克那种用接口来维护的话 是可以用keyof GameEvent拿到字符串作为key的

interface GameEvent {
    XXXEvent(param1: string, param2: number): void;
}

不过这样有个困扰 可能需要把所有事件类型都放到一个接口里维护 我希望能够进行分类 所以才有了上面发的用类的静态方法来枚举GameEvent.UIEvent.XXXEvent

class BattleEvent { }
class UIEvent {
    static XXXEvent(param1: string, param2: number) { }
}
class GameEvent {
    static BattleEvent: typeof BattleEvent = BattleEvent;
    static UIEvent: typeof UIEvent = UIEvent;    
}

然后我是通过event.toString().slice(0, event.toString().indexOf('('));将方法转成字符串然后提取方法名来作为key :joy:

可能办法有点笨吧 :joy: 但类型安全用起来还不赖
emit(GameEvent.UIEvent.XXXEvent, '123', 321);

太复杂了,发个消息还要定义一堆内容,完全丢失了TS的易用性

ts的易用性是对使用者来说的 ts这东西本来就是要求别人而不是要求自己的 所以写起来痛苦用起来爽

算了,不争了,怎么方便怎么来

22222222222 :joy:

第二种但是我用枚举 字符串 哪里注册的、派发的懒得找

想法很好 汲取成功 :face_with_raised_eyebrow:

我设计时候的想法是要区分可以通过 new event_target,而不是使用全局唯一的 event_target,而且就算用全局唯一的 event_target,也可以使用 event_interface & event_interface2 合并类型分离,但是不能用相同的事件键名,但是如果有编辑器会提示

重点是事件系统并不复杂啊,完全可以通过增加字符串的复杂度来避免重复,为啥一定要用单个单词做事件名

可能是习惯原因 我都是用类来实现枚举 :rofl:感谢提醒 刚刚我去加了个方法遍历检查重复事件名称