cross-magic
Version:
跨平台公共模块
149 lines (129 loc) • 3.71 kB
text/typescript
type ListenerCell = {
listener: Function
thisObject: any
priority: number
}
type ListenerMap = {
[type: string]: Array<ListenerCell>
}
export type Event = {
type: string
data: any
}
/**
* 事件发射器(发布订阅)
*/
export default class EventDispatcher {
public static EVENT_MAX: number = 100 // 最多能监听100个事件
public static EVENT_CELL_MAX: number = 1000 // 同一个事件最多能添加1000个监听函数
private listenerMap: ListenerMap = {}
/**
* 注册监听事件
* 注意:注册监听函数时,会根据listener,thisObject来进行去重判断,
* 当listener,thisObject都相同时,则会认为是同一个事件监听,不会将其注册进处理列表
* @param type 监听事件的类型
* @param listener 监听函数
* @param thisObject 监听函数的this指向
* @param priority 监听函数的优先级
*/
addEventListener(type: string, listener: Function, thisObject: any, priority?: number) {
if (!listener || !thisObject) {
console.warn('EventDispatcher addEventListener listener or thisObject is null')
return
}
const typeNum: number = Object.keys(this.listenerMap).length
if (!this.listenerMap[type]) {
if (!(typeNum >= EventDispatcher.EVENT_MAX)) {
this.listenerMap[type] = []
this._insertEventListener(this.listenerMap[type], listener, thisObject, priority)
} else {
console.warn(`addEventListener eventtype overflow limit:${EventDispatcher.EVENT_MAX}`)
}
return
}
if (this.listenerMap[type].length >= EventDispatcher.EVENT_CELL_MAX) {
console.warn(
`addEventListener eventCellType overflow limit:${EventDispatcher.EVENT_CELL_MAX}`
)
return
}
this._insertEventListener(this.listenerMap[type], listener, thisObject, priority)
}
/**
* 移除监听函数
* @param type 事件类型
* @param listener 事件处理函数
* @param thisObject 事件处理函数this指向
*/
removeEventListener(type: string, listener: Function, thisObject: any) {
if (!type || !listener) {
return
}
let list: Array<ListenerCell> = this.listenerMap[type]
if (!list || list.length <= 0) {
return
}
for (let i = list.length - 1; i >= 0; --i) {
if (list[i].listener === listener && list[i].thisObject === thisObject) {
list.splice(i, 1)
break
}
}
}
/**
* 触发事件
* @param event 事件数据
*/
dispatchEvent(event: Event) {
if (!event || !event.type) {
console.log('dispatchEvent event is null')
return
}
let eventList: Array<ListenerCell> = this.listenerMap[event.type]
if (!eventList || eventList.length <= 0) {
return
}
for (let i = 0; i < eventList.length; ++i) {
if (eventList[i].listener) {
eventList[i]
}
}
}
private _insertEventListener(
list: Array<ListenerCell>,
listener: Function,
thisObject: any,
priority?: number
) {
if (priority) {
priority = +priority | 0
} else {
priority = 0
}
let insertIndex = -1
for (let i = 0; i < list.length; ++i) {
let cell: ListenerCell = list[i]
if (cell.listener === listener && cell.thisObject === thisObject) {
return false
}
if (insertIndex === -1 && priority > cell.priority) {
insertIndex = i
break
}
}
if (insertIndex === -1) {
list.push({
listener,
thisObject,
priority
})
} else {
list.splice(insertIndex, 0, {
listener,
thisObject,
priority
})
}
return true
}
}