Files
vue-desktop/.qoder/repowiki/zh/content/事件系统/事件系统.md
2025-09-24 16:43:10 +08:00

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)

目录

  1. 简介
  2. 核心组件分析
  3. 接口契约规范
  4. 事件管理器扩展实现
  5. 跨组件通信实例
  6. 错误处理与内存泄漏防范

简介

本文档全面记录了自定义事件总线系统的实现原理与使用方法。基于 EventBuilderImpl 类,详细解释 addEventListenerremoveEventListenernotifyEvent 三个核心方法的工作机制,包括 onceimmediate 等选项的行为特征。文档描述了 IEventBuilder 接口的契约规范,并分析了 DesktopEventManagerWindowFormEventManager 如何继承和扩展基础事件功能。同时提供跨组件通信的实际用例,并说明错误处理和内存泄漏防范措施。

核心组件分析

EventBuilderImpl 实现机制

EventBuilderImpl 是事件总线系统的核心实现类,采用泛型设计支持类型安全的事件管理。其内部通过 Map<keyof Events, Set<HandlerWrapper<Events[keyof Events]>>> 结构存储事件处理器,确保高效的事件查找与去重。

addEventListener 方法工作机制

该方法用于注册事件监听器,具有以下特性:

  • 去重机制:在添加前检查是否已存在相同处理器函数,避免重复绑定
  • 即时执行:当 options.immediatetrue 时,立即同步执行一次处理器
  • 单次监听:通过 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

错误处理与内存泄漏防范

错误处理机制

系统在关键执行路径上均包含异常捕获:

  • 处理器执行时捕获异常,防止中断其他监听器
  • 控制台输出错误信息便于调试
  • 不抛出异常保证事件总线稳定性

内存泄漏防范措施

  1. 及时解绑:使用 removeEventListener 移除不再需要的监听器
  2. 单次监听:对只需执行一次的逻辑使用 once: true 选项
  3. 资源清理:实现 destroy() 方法清空所有事件处理器
  4. 实例管理:通过单例模式管理事件总线实例生命周期
flowchart TD
A[组件挂载] --> B[添加事件监听]
B --> C[设置once或immediate]
C --> D[组件运行]
D --> E{组件卸载?}
E --> |是| F[调用removeEventListener]
F --> G[或调用destroy清理所有]
G --> H[防止内存泄漏]
E --> |否| D

Section sources