# 窗口关闭事件 **Referenced Files in This Document ** - [WindowFormEventManager.ts](file://src/events/WindowFormEventManager.ts) - [EventBuilderImpl.ts](file://src/events/impl/EventBuilderImpl.ts) - [DesktopEventManager.ts](file://src/events/DesktopEventManager.ts) ## 目录 1. [简介](#简介) 2. [核心职责与生命周期管理](#核心职责与生命周期管理) 3. [事件定义与接口规范](#事件定义与接口规范) 4. [事件注册与监听机制](#事件注册与监听机制) 5. [事件广播与跨组件通信](#事件广播与跨组件通信) 6. [资源清理与内存泄漏防护](#资源清理与内存泄漏防护) 7. [完整示例:带确认对话框的关闭流程](#完整示例:带确认对话框的关闭流程) 8. [总结](#总结) ## 简介 `windowFormClose` 事件是 Vue 桌面应用中用于管理窗口实例销毁的核心机制。当用户点击窗口右上角的关闭按钮时,系统会触发该事件,并携带目标窗口的唯一标识符(ID),以精确地定位并销毁对应的窗口实例。此事件不仅负责 UI 层面的 DOM 移除,还承担着状态存储更新、资源释放以及防止内存泄漏的重要职责。 本文档将深入解析 `windowFormClose` 事件的整个生命周期,涵盖其定义、注册、广播及处理过程,并说明如何通过 `wfem`(Window Form Event Manager)进行监听器注册,集成用户确认逻辑,并确保系统的安全性和一致性。 ## 核心职责与生命周期管理 `windowFormClose` 事件在窗口关闭流程中扮演着中枢角色,其生命周期贯穿从用户交互到最终资源回收的全过程: 1. **触发阶段**:由用户点击关闭按钮发起,事件携带窗口 ID 作为参数。 2. **广播阶段**:通过 `wfem.notifyEvent('windowFormClose', id)` 将事件分发至所有注册的监听器。 3. **处理阶段**:各组件根据自身业务逻辑响应事件,执行如显示确认对话框、保存未提交数据等操作。 4. **清理阶段**:完成必要检查后,执行 DOM 节点移除、状态 store 更新和相关资源释放。 5. **终止阶段**:确保所有引用被清除,避免因闭包或事件监听器残留导致的内存泄漏。 该事件的设计遵循单一职责原则,专注于“关闭”这一核心动作,同时通过松耦合的发布-订阅模式实现跨组件协作。 **Section sources** - [WindowFormEventManager.ts](file://src/events/WindowFormEventManager.ts#L27-L27) ## 事件定义与接口规范 `windowFormClose` 事件在 `IWindowFormEvent` 接口中明确定义,位于 `src/events/WindowFormEventManager.ts` 文件中。该接口继承自通用事件映射类型 `IEventMap`,并声明了多个与窗口操作相关的事件处理器签名。 ```typescript interface IWindowFormEvent extends IEventMap { /** * 窗口关闭 * @param id 窗口id */ windowFormClose: (id: string) => void; // 其他事件... } ``` 此定义明确了以下关键信息: - **事件名称**:`windowFormClose` - **参数类型**:单个字符串类型的 `id`,用于唯一标识待关闭的窗口实例。 - **返回类型**:`void`,表示该事件不期望返回值,主要用于触发副作用。 这种强类型的接口设计保证了事件使用的安全性,编译器能够在开发阶段捕获类型错误。 ```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 IEventMap { <> } IWindowFormEvent --|> IEventMap : 继承 ``` **Diagram sources ** - [WindowFormEventManager.ts](file://src/events/WindowFormEventManager.ts#L7-L42) **Section sources** - [WindowFormEventManager.ts](file://src/events/WindowFormEventManager.ts#L7-L42) ## 事件注册与监听机制 系统使用 `wfem`(`WindowFormEventManager` 的实例)作为 `windowFormClose` 事件的管理中心。开发者可通过 `addEventListener` 方法注册监听器,语法如下: ```typescript wfem.addEventListener('windowFormClose', (id) => { // 处理关闭逻辑 }); ``` `wfem` 是基于 `EventBuilderImpl` 类构建的事件总线实例,它提供了类型安全的事件注册、移除和通知功能。`addEventListener` 方法支持可选参数,例如 `immediate` 可用于在注册时立即执行一次回调,`once` 则确保监听器仅响应一次事件。 这种机制允许任意组件在需要时订阅关闭事件,而无需直接依赖具体的窗口管理逻辑,实现了高度的解耦。 ```mermaid sequenceDiagram participant User as 用户 participant UI as UI组件 participant Wfem as wfem(事件管理器) participant Listener as 关闭监听器 User->>UI : 点击关闭按钮 UI->>Wfem : notifyEvent("windowFormClose", windowId) Wfem->>Listener : 执行所有注册的监听器 Listener-->>Wfem : 返回 Wfem-->>UI : 事件处理完毕 ``` **Diagram sources ** - [WindowFormEventManager.ts](file://src/events/WindowFormEventManager.ts#L60-L60) - [EventBuilderImpl.ts](file://src/events/impl/EventBuilderImpl.ts#L7-L95) **Section sources** - [WindowFormEventManager.ts](file://src/events/WindowFormEventManager.ts#L60-L60) ## 事件广播与跨组件通信 `windowFormClose` 事件的广播能力由 `EventBuilderImpl` 类的 `notifyEvent` 方法实现。该方法遍历内部存储的所有监听器,并按顺序调用它们。这种发布-订阅模式是实现跨组件通信的关键。 其优势在于: - **低耦合**:发送者(如窗口控件)无需知道接收者的存在,只需关注事件的发出。 - **高内聚**:每个监听器只需关注与自己相关的业务逻辑,例如一个监听器负责弹出确认框,另一个负责清理定时器。 - **可扩展性**:可以轻松添加新的监听器来增强关闭流程的功能,而无需修改现有代码。 事件广播确保了所有相关方都能及时收到关闭通知,从而协同完成复杂的清理任务,维护了系统状态的一致性。 ```mermaid graph TB A[窗口A] --> |notifyEvent| B(wfem) C[窗口B] --> |notifyEvent| B D[其他组件] --> |notifyEvent| B B --> E[监听器1] B --> F[监听器2] B --> G[监听器N] ``` **Diagram sources ** - [EventBuilderImpl.ts](file://src/events/impl/EventBuilderImpl.ts#L7-L95) ## 资源清理与内存泄漏防护 正确处理 `windowFormClose` 事件是防止内存泄漏的核心环节。一个完整的清理流程应包括: 1. **DOM 移除**:从虚拟 DOM 和真实 DOM 中卸载窗口及其子组件。 2. **状态更新**:在全局状态 store(如 Pinia 或 Vuex)中移除对应窗口的状态条目。 3. **事件解绑**:移除该窗口实例上注册的所有自定义事件监听器。 4. **资源释放**:清除与该窗口关联的定时器(`setInterval`, `setTimeout`)、WebSocket 连接或其他长生命周期对象。 `EventBuilderImpl` 内部通过 `Set` 数据结构管理监听器,并在每次事件通知后检查 `once` 标志,自动清理一次性监听器。此外,`destroy` 方法可用于彻底清空所有事件处理器,为整个事件管理器的销毁提供支持。 **Section sources** - [EventBuilderImpl.ts](file://src/events/impl/EventBuilderImpl.ts#L7-L95) ## 完整示例:带确认对话框的关闭流程 以下是一个典型的 `windowFormClose` 事件监听器实现,集成了用户确认对话框和资源释放逻辑: ```typescript wfem.addEventListener('windowFormClose', async (id) => { const shouldClose = await showConfirmDialog(`确定要关闭窗口 ${id} 吗?`); if (!shouldClose) return; // 用户取消,中断关闭流程 // 1. 清理特定于该窗口的资源 cleanupWindowResources(id); // 2. 从状态store中移除窗口记录 windowStore.removeWindow(id); // 3. 触发DOM移除(通常由组件自身在状态变更后自动处理) console.log(`窗口 ${id} 已成功关闭并清理`); }, { once: false }); // 保持监听器长期有效 ``` 在此示例中: - 使用异步函数等待用户确认。 - 若用户取消,则直接返回,阻止后续清理操作。 - 按照逻辑顺序执行资源清理、状态更新等步骤。 - 监听器设置为持久性(`once: false`),以便能响应未来可能发生的同类型事件。 ## 总结 `windowFormClose` 事件是 Vue 桌面应用中窗口管理模块的基石。它通过清晰的接口定义、高效的事件广播机制和严谨的资源清理策略,确保了窗口实例能够被安全、可靠地销毁。借助 `wfem` 事件总线,系统实现了组件间的松耦合通信,使得复杂的关闭流程可以被分解为多个独立、可维护的监听器。遵循本文档所述的最佳实践,可以有效避免内存泄漏,保障应用的长期稳定运行。