131 lines
7.2 KiB
Markdown
131 lines
7.2 KiB
Markdown
|
|
<cite>
|
|||
|
|
**本文档中引用的文件**
|
|||
|
|
- [WindowFormEventManager.ts](file://src/events/WindowFormEventManager.ts)
|
|||
|
|
- [useClickFocus.ts](file://src/common/hooks/useClickFocus.ts)
|
|||
|
|
- [useObservableVue.ts](file://src/common/hooks/useObservableVue.ts)
|
|||
|
|
- [EventBuilderImpl.ts](file://src/events/impl/EventBuilderImpl.ts)
|
|||
|
|
</cite>
|
|||
|
|
|
|||
|
|
## 目录
|
|||
|
|
1. [窗口聚焦事件](#窗口聚焦事件)
|
|||
|
|
2. [用户交互背景](#用户交互背景)
|
|||
|
|
3. [技术实现机制](#技术实现机制)
|
|||
|
|
4. [多窗口层级管理](#多窗口层级管理)
|
|||
|
|
5. [Vue组件中的事件监听](#vue组件中的事件监听)
|
|||
|
|
6. [响应式状态更新](#响应式状态更新)
|
|||
|
|
7. [用户体验影响](#用户体验影响)
|
|||
|
|
|
|||
|
|
## 窗口聚焦事件
|
|||
|
|
|
|||
|
|
`windowFormFocus` 事件是桌面级Vue应用中用于管理窗口激活状态的核心事件。当用户点击或通过其他方式激活某个窗口时,该事件被触发并广播被激活窗口的唯一标识符(id),从而驱动UI层面对应的视觉反馈和状态变更。
|
|||
|
|
|
|||
|
|
**Section sources**
|
|||
|
|
- [WindowFormEventManager.ts](file://src/events/WindowFormEventManager.ts#L32-L32)
|
|||
|
|
|
|||
|
|
## 用户交互背景
|
|||
|
|
|
|||
|
|
在模拟传统桌面操作系统的Web应用中,用户期望拥有与原生应用一致的窗口交互体验。当用户点击一个处于非顶层的窗口时,该窗口应当自动移动到所有其他窗口的前面,并获得输入焦点。这种行为符合用户的直觉认知,即“所见即所得”的交互原则。`windowFormFocus` 事件正是为了捕捉这一关键的用户意图而设计的,它作为用户操作与系统响应之间的桥梁,确保了界面行为的可预测性和一致性。
|
|||
|
|
|
|||
|
|
**Section sources**
|
|||
|
|
- [WindowFormEventManager.ts](file://src/events/WindowFormEventManager.ts#L30-L34)
|
|||
|
|
|
|||
|
|
## 技术实现机制
|
|||
|
|
|
|||
|
|
`windowFormFocus` 事件的技术实现依赖于一个名为 `wfem` (Window Form Event Manager) 的全局事件管理器实例,该实例基于 `EventBuilderImpl` 类构建,提供了一套完整的发布-订阅模式接口。
|
|||
|
|
|
|||
|
|
事件的触发流程如下:
|
|||
|
|
1. **事件定义**:在 `IWindowFormEvent` 接口中明确定义了 `windowFormFocus(id: string)` 方法签名。
|
|||
|
|
2. **事件触发**:当检测到用户对特定窗口的点击操作时,业务逻辑代码会调用 `wfem.notifyEvent('windowFormFocus', windowId)` 来广播该事件。
|
|||
|
|
3. **事件监听**:任何需要对此事件做出反应的组件都可以通过 `wfem.addEventListener('windowFormFocus', callback)` 注册一个回调函数。
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
sequenceDiagram
|
|||
|
|
participant User as 用户
|
|||
|
|
participant Window as 窗口组件
|
|||
|
|
participant Hook as useClickFocus Hook
|
|||
|
|
participant EventManager as wfem (事件管理器)
|
|||
|
|
User->>Window : 点击窗口
|
|||
|
|
Window->>Hook : 触发内部处理
|
|||
|
|
Hook->>EventManager : 调用 notifyEvent('windowFormFocus', id)
|
|||
|
|
EventManager->>EventManager : 遍历所有监听器
|
|||
|
|
loop 通知所有订阅者
|
|||
|
|
EventManager-->>Subscriber : 执行注册的回调函数
|
|||
|
|
end
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Diagram sources**
|
|||
|
|
- [WindowFormEventManager.ts](file://src/events/WindowFormEventManager.ts#L60-L60)
|
|||
|
|
- [useClickFocus.ts](file://src/common/hooks/useClickFocus.ts#L13-L64)
|
|||
|
|
|
|||
|
|
## 多窗口层级管理
|
|||
|
|
|
|||
|
|
在存在多个重叠窗口的应用场景下,维护正确的渲染顺序至关重要。`windowFormFocus` 事件在此扮演了核心角色。每当该事件被触发,其携带的窗口ID会被传递给负责管理窗口栈的逻辑模块。该模块会根据ID找到对应的窗口元素,并将其CSS `z-index` 属性提升至最高层级,同时移除之前处于顶层窗口的焦点样式,并为当前窗口应用新的焦点样式(如高亮边框)。这一系列操作确保了被激活的窗口始终位于最前端,解决了视觉遮挡问题,使用户能够清晰地识别出当前正在操作的对象。
|
|||
|
|
|
|||
|
|
**Section sources**
|
|||
|
|
- [WindowFormEventManager.ts](file://src/events/WindowFormEventManager.ts#L30-L34)
|
|||
|
|
|
|||
|
|
## Vue组件中的事件监听
|
|||
|
|
|
|||
|
|
在Vue组件中监听 `windowFormFocus` 事件是一个标准的异步编程实践。开发者可以在组件的 `setup` 函数或 `onMounted` 生命周期钩子中,使用 `wfem.addEventListener` 方法注册一个监听器。最佳实践是将此逻辑封装在一个自定义Hook中,以保证代码的复用性和可维护性。例如,可以创建一个 `useWindowFocusListener` Hook,在组件挂载时订阅事件,并在组件卸载前 (`onBeforeUnmount`) 及时移除监听器,防止内存泄漏。
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
flowchart TD
|
|||
|
|
A[组件挂载] --> B["调用 wfem.addEventListener('windowFormFocus', callback)"]
|
|||
|
|
B --> C[事件管理器注册回调]
|
|||
|
|
D[用户点击窗口] --> E["触发 wfem.notifyEvent('windowFormFocus', id)"]
|
|||
|
|
E --> F[事件管理器遍历并执行所有回调]
|
|||
|
|
F --> G[组件中的回调函数被调用]
|
|||
|
|
G --> H[更新组件内部状态]
|
|||
|
|
I[组件卸载] --> J["调用 wfem.removeEventListener 移除监听"]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Diagram sources**
|
|||
|
|
- [WindowFormEventManager.ts](file://src/events/WindowFormEventManager.ts#L60-L60)
|
|||
|
|
- [useClickFocus.ts](file://src/common/hooks/useClickFocus.ts#L13-L64)
|
|||
|
|
|
|||
|
|
## 响应式状态更新
|
|||
|
|
|
|||
|
|
为了实现高效且直观的状态管理,建议结合 `useObservableVue` 这一自定义Hook来处理 `windowFormFocus` 事件带来的状态变化。`useObservableVue` 将一个实现了 `IObservable<T>` 接口的可观察对象转换为Vue的响应式对象。当 `windowFormFocus` 事件触发时,其回调函数可以直接修改存储在可观察对象中的 `activeWindow` 状态。由于 `useObservableVue` 内部建立了双向同步机制,对可观察对象的任何修改都会立即反映到Vue的响应式系统中,从而自动触发相关组件的重新渲染,无需手动调用 `forceUpdate` 或进行复杂的 `$emit` 操作。
|
|||
|
|
|
|||
|
|
```mermaid
|
|||
|
|
classDiagram
|
|||
|
|
class IObservable~T~ {
|
|||
|
|
<<interface>>
|
|||
|
|
+subscribe(callback) : () => void
|
|||
|
|
+toRefsProxy() : T
|
|||
|
|
}
|
|||
|
|
class ObservableImpl~T~ {
|
|||
|
|
-state : T
|
|||
|
|
-observers : Set~() => void~
|
|||
|
|
+subscribe(callback) : () => void
|
|||
|
|
+toRefsProxy() : T
|
|||
|
|
+notify() : void
|
|||
|
|
}
|
|||
|
|
class useObservableVue {
|
|||
|
|
+useObservable(observable) : Reactive~T~
|
|||
|
|
}
|
|||
|
|
class Component {
|
|||
|
|
+setup()
|
|||
|
|
+template
|
|||
|
|
}
|
|||
|
|
IObservable~T~ <|.. ObservableImpl~T~ : 实现
|
|||
|
|
useObservableVue --> IObservable~T~ : 使用
|
|||
|
|
Component --> useObservableVue : 调用
|
|||
|
|
ObservableImpl~T~ --> Component : 通过响应式更新视图
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Diagram sources**
|
|||
|
|
- [useObservableVue.ts](file://src/common/hooks/useObservableVue.ts#L13-L87)
|
|||
|
|
- [EventBuilderImpl.ts](file://src/events/impl/EventBuilderImpl.ts#L1-L96)
|
|||
|
|
|
|||
|
|
## 用户体验影响
|
|||
|
|
|
|||
|
|
`windowFormFocus` 事件对桌面级应用的用户体验具有决定性的影响。它直接决定了应用是否能提供流畅、自然的多任务操作环境。一个正确实现的窗口聚焦机制能够:
|
|||
|
|
- **降低认知负荷**:用户无需思考哪个窗口是活动的,视觉反馈清晰明确。
|
|||
|
|
- **提高操作效率**:通过简单的点击即可切换上下文,符合肌肉记忆。
|
|||
|
|
- **增强应用可信度**:其行为与用户熟悉的操作系统保持一致,提升了应用的专业感和可靠性。
|
|||
|
|
|
|||
|
|
反之,如果该事件处理不当,例如出现窗口无法置顶、焦点丢失或样式错乱等问题,将严重破坏用户对应用的信任,导致挫败感和使用障碍。因此,确保 `windowFormFocus` 事件的稳定性和准确性是构建高质量桌面级Web应用的关键基石。
|
|||
|
|
|
|||
|
|
**Section sources**
|
|||
|
|
- [WindowFormEventManager.ts](file://src/events/WindowFormEventManager.ts#L30-L34)
|