摘要
CocosCreator 有着内置的事件系统,我们用起来也很是方便。那么我们自己如何简单的实现一个 EventManager 呢?KUOKUO 通过一个小例子带你学习。
正文
使用版本
CocosCreator 版本 2.2.2
明确目标
我们要做一个事件管理模块,实现事件的监听方法 on,取消方法 off,事件发送 emit。

事件数据类型
首先,我们要想好事件用什么存储。选择用 Map,则需要一个事件名称,类型 string,还有就是一个对象,存放 callback 以及调用者 target。让我们规定一下类型:
interface EventData { callback: Function, target: any }
|
存储 Map
让我们写出类的名称:
export class EventManager { }
|
声明其私有的 Map:
private eventsMap: Map<string, EventData> = new Map()
|
存入事件
on 的实现就是将传入的参数进行存储,如果这个事件已经有了,就覆盖掉:
public on (eventName: string, callback: Function, target: any) { if (this.eventsMap.has(eventName)) { console.warn(`${eventName} 事件已存在,覆盖`) } this.eventsMap.set(eventName, { callback, target }) }
|
与之对应的取消监听,就是将事件从 Map 中删除:
public off (eventName: string) { if (!this.eventsMap.has(eventName)) { console.warn(`${eventName} 事件不存在`) return } this.eventsMap.delete(eventName) }
|
事件的发送
最重要的一步是事件的发送,我们首先要取到 Map 中对应的事件,然后利用 call 或者 apply 使其在 target 的作用域下被调用(使用箭头函数会使得这个 target 无效,会指向声明时的 this)。
public emit (eventName: string, data: any) { if (!this.eventsMap.has(eventName)) { console.warn(`${eventName} 事件不存在`) return } const { callback, target } = this.eventsMap.get(eventName) callback.call(target, data) }
|
data 参数可以拓展多个,但是实际上用对象包住,一个也是可以的,比如测试代码:
this.eventManager.emit('event1', { data1: 'kuokuo', data2: [6, 6, 6] })
|
实际测试
写一个测试脚本,里面做两个事件监听,新建两个按钮,分别绑定到脚本中的 onClick 方法:
import { EventManager } from "./EventManager" const {ccclass, property} = cc._decorator
@ccclass export default class Test extends cc.Component {
eventManager: EventManager = new EventManager()
onLoad () { this.eventManager.on('event1', (data) => { console.log('事件1触发,数据为:') console.log(data) }, this) this.eventManager.on('event2', (data) => { console.log('事件2触发,数据为:') console.log(data) }, this) }
onClick_1 () { this.eventManager.emit('event1', { data1: 'kuokuo', data2: [6, 6, 6] }) }
onClick_2 () { this.eventManager.emit('event2', 23333) }
}
|

起个名字
不同于单例模式,这个事件类可以实例化多份,我们可以搞个“起名字方法”,最后代码:
interface EventData { callback: Function, target: any }
export class EventManager {
private eventsMap: Map<string, EventData> = new Map()
private name: string = undefined
public setEventManagerName (name: string) { this.name = name }
public getEventManagerName (): string { return this.name === undefined ? 'event-manager' : this.name }
public on (eventName: string, callback: Function, target: any) { if (this.eventsMap.has(eventName)) { console.warn(`${eventName} 事件已存在,覆盖`) } this.eventsMap.set(eventName, { callback, target }) }
public emit (eventName: string, data: any) { if (!this.eventsMap.has(eventName)) { console.warn(`${eventName} 事件不存在`) return } const { callback, target } = this.eventsMap.get(eventName) callback.call(target, data) }
public off (eventName: string) { if (!this.eventsMap.has(eventName)) { console.warn(`${eventName} 事件不存在`) return } this.eventsMap.delete(eventName) }
}
|
结语
有 on 必有 off,不要让对象“假释放”哦,Map 中还有引用呢!
文章有没有带给你收获呢!O(∩_∩)O~~
微信公众号
