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