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