8.9 KiB
事件系统
**Referenced Files in This Document ** - [EventBuilderImpl.ts](file://src/events/impl/EventBuilderImpl.ts) - [IEventBuilder.ts](file://src/events/IEventBuilder.ts) - [DesktopEventManager.ts](file://src/events/DesktopEventManager.ts) - [WindowFormEventManager.ts](file://src/events/WindowFormEventManager.ts)目录
简介
本文档全面记录了自定义事件总线系统的实现原理与使用方法。基于 EventBuilderImpl 类,详细解释 addEventListener、removeEventListener 和 notifyEvent 三个核心方法的工作机制,包括 once、immediate 等选项的行为特征。文档描述了 IEventBuilder 接口的契约规范,并分析了 DesktopEventManager 和 WindowFormEventManager 如何继承和扩展基础事件功能。同时提供跨组件通信的实际用例,并说明错误处理和内存泄漏防范措施。
核心组件分析
EventBuilderImpl 实现机制
EventBuilderImpl 是事件总线系统的核心实现类,采用泛型设计支持类型安全的事件管理。其内部通过 Map<keyof Events, Set<HandlerWrapper<Events[keyof Events]>>> 结构存储事件处理器,确保高效的事件查找与去重。
addEventListener 方法工作机制
该方法用于注册事件监听器,具有以下特性:
- 去重机制:在添加前检查是否已存在相同处理器函数,避免重复绑定
- 即时执行:当
options.immediate为true时,立即同步执行一次处理器 - 单次监听:通过
options.once标记,使监听器在触发后自动移除 - 类型安全:利用 TypeScript 泛型约束确保事件名与处理器参数类型匹配
flowchart TD
Start([开始]) --> ValidateHandler["验证处理器非空"]
ValidateHandler --> HasEvent{"是否存在事件队列?"}
HasEvent --> |否| CreateSet["创建新的处理器集合"]
CreateSet --> AddToSet
HasEvent --> |是| GetSet["获取现有集合"]
GetSet --> AddToSet
AddToSet --> CheckDuplicate{"是否已存在?"}
CheckDuplicate --> |否| AddWrapper["添加包装器(once标记)"]
AddWrapper --> CheckImmediate{"是否立即执行?"}
CheckImmediate --> |是| ExecuteNow["立即执行处理器"]
CheckImmediate --> |否| End([结束])
ExecuteNow --> End
Diagram sources
removeEventListener 方法工作机制
该方法通过遍历对应事件的处理器集合,精确匹配并删除指定的处理器函数引用,实现精准解绑。
notifyEvent 方法工作机制
通知方法按顺序调用所有注册的处理器,并处理以下特殊情况:
- 自动清理标记为
once的监听器 - 捕获并记录处理器执行中的异常,防止中断其他监听器
- 支持任意数量的参数传递
sequenceDiagram
participant Publisher as "发布者"
participant EventBus as "EventBus"
participant Handler1 as "处理器1"
participant Handler2 as "处理器2"
Publisher->>EventBus : notifyEvent('event', args)
EventBus->>EventBus : 获取处理器集合
loop 每个处理器
EventBus->>Handler1 : 执行处理器
Handler1-->>EventBus : 完成
EventBus->>EventBus : 检查once标记
alt 是单次监听
EventBus->>EventBus : 从集合中移除
end
EventBus->>Handler2 : 执行处理器
Handler2-->>EventBus : 完成
end
EventBus-->>Publisher : 通知完成
Note over Handler1,Handler2 : 异常被捕获,不影响其他处理器执行
Diagram sources
Section sources
接口契约规范
IEventBuilder 接口定义
IEventBuilder 接口定义了事件管理器的标准行为契约,继承自 IDestroyable 接口以支持资源清理。
classDiagram
class IEventBuilder {
<<interface>>
+addEventListener(eventName, handler, options) : void
+removeEventListener(eventName, handler) : void
+notifyEvent(eventName, ...args) : void
}
class IDestroyable {
<<interface>>
+destroy() : void
}
IEventBuilder --|> IDestroyable : 继承
class EventBuilderImpl {
-_eventHandlers : Map<string, Set<HandlerWrapper>>
+addEventListener()
+removeEventListener()
+notifyEvent()
+destroy()
}
EventBuilderImpl ..|> IEventBuilder : 实现
Diagram sources
接口方法参数说明:
| 方法 | 参数 | 类型 | 描述 |
|---|---|---|---|
| addEventListener | eventName | keyof Events | 事件名称 |
| handler | F extends Events[E] | 事件处理器函数 | |
| options | {immediate?: boolean, immediateArgs?: Parameters, once?: boolean} | 配置选项 | |
| removeEventListener | eventName | keyof Events | 事件名称 |
| handler | F extends Events[E] | 要移除的处理器函数 | |
| notifyEvent | eventName | keyof Events | 事件名称 |
| ...args | Parameters | 传递给处理器的参数 |
Section sources
事件管理器扩展实现
DesktopEventManager 桌面事件管理
DesktopEventManager 通过实例化 EventBuilderImpl<IDesktopEvent> 创建专用的桌面事件总线,定义了桌面应用相关的特定事件类型。
classDiagram
class IDesktopEvent {
<<interface>>
+desktopAppPosChange(info : IDesktopAppIcon) : void
}
class desktopEM {
+instance of EventBuilderImpl<IDesktopEvent>
}
desktopEM ..> IDesktopEvent : 类型约束
desktopEM ..> EventBuilderImpl : 实例化
Diagram sources
WindowFormEventManager 窗口表单事件管理
WindowFormEventManager 提供了窗口生命周期管理的完整事件体系,涵盖最小化、最大化、关闭、聚焦等状态变化。
classDiagram
class IWindowFormEvent {
<<interface>>
+windowFormMinimize(id : string) : void
+windowFormMaximize(id : string) : void
+windowFormRestore(id : string) : void
+windowFormClose(id : string) : void
+windowFormFocus(id : string) : void
+windowFormDataUpdate(data : IWindowFormDataUpdateParams) : void
+windowFormCreated() : void
}
class wfem {
+instance of EventBuilderImpl<IWindowFormEvent>
}
class IWindowFormDataUpdateParams {
+id : string
+state : TWindowFormState
+width : number
+height : number
+x : number
+y : number
}
wfem ..> IWindowFormEvent : 类型约束
IWindowFormEvent ..> IWindowFormDataUpdateParams : 引用
Diagram sources
Section sources
跨组件通信实例
桌面应用位置更新场景
// 发布者组件
const updatePosition = (iconInfo) => {
desktopEM.notifyEvent('desktopAppPosChange', iconInfo)
}
// 订阅者组件
desktopEM.addEventListener('desktopAppPosChange', (info) => {
console.log('应用位置更新:', info.name, info.x, info.y)
}, {
immediate: true,
immediateArgs: [currentIconInfo]
})
窗口状态变更场景
// 窗口最小化
wfem.notifyEvent('windowFormMinimize', 'win123')
// 监听窗口最小化(仅一次)
wfem.addEventListener('windowFormMinimize', (id) => {
addToTaskbar(id)
}, {
once: true
})
// 监听所有窗口数据更新
wfem.addEventListener('windowFormDataUpdate', (data) => {
saveWindowState(data)
})
Section sources
错误处理与内存泄漏防范
错误处理机制
系统在关键执行路径上均包含异常捕获:
- 处理器执行时捕获异常,防止中断其他监听器
- 控制台输出错误信息便于调试
- 不抛出异常保证事件总线稳定性
内存泄漏防范措施
- 及时解绑:使用
removeEventListener移除不再需要的监听器 - 单次监听:对只需执行一次的逻辑使用
once: true选项 - 资源清理:实现
destroy()方法清空所有事件处理器 - 实例管理:通过单例模式管理事件总线实例生命周期
flowchart TD
A[组件挂载] --> B[添加事件监听]
B --> C[设置once或immediate]
C --> D[组件运行]
D --> E{组件卸载?}
E --> |是| F[调用removeEventListener]
F --> G[或调用destroy清理所有]
G --> H[防止内存泄漏]
E --> |否| D
Section sources