interface IEventsMap { [key: string]: any }
type Handler<T = unknown> = (data: T) => void
export default class Event<Events extends IEventsMap> {
key = new Proxy<{ [key in keyof Events]: key }>(Object.create(null), {
get: (_, key) => key
})
private events = new Map<keyof Events, Array<[unknown, Handler<Events[keyof Events]>]>>()
private getHandlers<Key extends keyof Events>(type: Key) {
let handlers = this.events.get(type)
if (!handlers) {
handlers = []
this.events.set(type, handlers)
}
return handlers
}
on<Key extends keyof Events>(type: Key, handler: Handler, target?: unknown) {
this.getHandlers(type).push([target, handler])
}
emit<Key extends keyof Events>(type: Key, data: Events[Key]) {
this.getHandlers(type).forEach(([target, handler]) => {
target ? handler.call(target, data) : handler(data)
})
}
off<Key extends keyof Events>(type: Key, handler?: Handler<Events[Key]>, target?: unknown) {
if (handler) {
const handlers = this.getHandlers(type)
const index = handlers.findIndex(value => {
return (value[0] === target && value[1] === handler)
})
handlers.splice(index >>> 0, 1)
} else {
this.events.set(type, [])
}
}
once<Key extends keyof Events>(type: Key, handler: Handler<Events[Key]>, target?: unknown) {
const callbackWrap = (data: Events[Key]) => {
target ? handler.call(target, data) : handler(data)
this.off(type, handler, target)
}
this.on(type, callbackWrap, target)
}
}
3赞
点赞点赞
提个建议啊,事件绑定的时候,很多情况需要绑定对象,比如A和B都有事件E,你在A节点off的时候直接吧E事件赋值空了的话,B节点也会受影响,建议加上校验
很抱歉,这应该是使用不当
是的,这个我忘记加了绑定上下文了,我现在考虑要不要加上, 因为箭头函数可以处理指向问题,但是继承又是问题
我在想使用装饰器处理,但是发现继承的this指向有问题,大佬有什么好的建议吗
直接继承 cc.EventTarget,最好的选择,也是最安全的做法
甚至实例化也可以直接用 cc.EventTarget,继承的类型只用作类型提示,不过这样不能用 key 了
赞同你的看法,EventTarget可以不必重复造轮子
额。。。,我不知道有这个
已支持上下文的



