提交文件
This commit is contained in:
330
.qoder/repowiki/zh/content/前端开发指南/状态管理.md
Normal file
330
.qoder/repowiki/zh/content/前端开发指南/状态管理.md
Normal file
@@ -0,0 +1,330 @@
|
||||
# 状态管理
|
||||
|
||||
<cite>
|
||||
**本文引用的文件**
|
||||
- [frontend/src/main.js](file://frontend/src/main.js)
|
||||
- [frontend/src/stores/index.js](file://frontend/src/stores/index.js)
|
||||
- [frontend/src/stores/user.js](file://frontend/src/stores/user.js)
|
||||
- [frontend/src/stores/app.js](file://frontend/src/stores/app.js)
|
||||
- [frontend/src/views/Login.vue](file://frontend/src/views/Login.vue)
|
||||
- [frontend/src/views/Layout.vue](file://frontend/src/views/Layout.vue)
|
||||
- [frontend/src/router/index.js](file://frontend/src/router/index.js)
|
||||
- [frontend/src/api/auth.js](file://frontend/src/api/auth.js)
|
||||
- [frontend/src/api/department.js](file://frontend/src/api/department.js)
|
||||
- [frontend/package.json](file://frontend/package.json)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构总览](#架构总览)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖关系分析](#依赖关系分析)
|
||||
7. [性能考量](#性能考量)
|
||||
8. [故障排查指南](#故障排查指南)
|
||||
9. [结论](#结论)
|
||||
10. [附录](#附录)
|
||||
|
||||
## 简介
|
||||
本指南围绕前端仓库中的 Pinia 状态管理进行系统化讲解,覆盖 Store 的创建、状态与动作的实现、模块化组织、跨组件共享、持久化策略、订阅与调试、异步与错误处理、以及状态重置与迁移等主题。结合项目实际的用户状态与应用配置状态实现,帮助开发者快速理解并高效扩展状态管理能力。
|
||||
|
||||
## 项目结构
|
||||
前端采用 Vue 3 + Pinia 架构,状态管理集中在 stores 目录,通过集中导出统一暴露给视图层;路由负责页面导航与鉴权守卫;API 层封装请求逻辑;入口文件完成 Pinia 的安装与挂载。
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "入口与框架"
|
||||
MAIN["main.js<br/>安装 Pinia 并挂载应用"]
|
||||
ROUTER["router/index.js<br/>路由与鉴权守卫"]
|
||||
end
|
||||
subgraph "状态层"
|
||||
STORES_INDEX["stores/index.js<br/>统一导出 Store"]
|
||||
USER["stores/user.js<br/>用户状态 Store"]
|
||||
APP["stores/app.js<br/>应用配置 Store"]
|
||||
end
|
||||
subgraph "视图层"
|
||||
LOGIN["views/Login.vue<br/>登录页"]
|
||||
LAYOUT["views/Layout.vue<br/>布局页"]
|
||||
end
|
||||
subgraph "API 层"
|
||||
AUTH_API["api/auth.js<br/>认证接口"]
|
||||
DEPT_API["api/department.js<br/>科室接口"]
|
||||
end
|
||||
MAIN --> STORES_INDEX
|
||||
STORES_INDEX --> USER
|
||||
STORES_INDEX --> APP
|
||||
LOGIN --> USER
|
||||
LAYOUT --> APP
|
||||
USER --> AUTH_API
|
||||
APP --> DEPT_API
|
||||
ROUTER --> LOGIN
|
||||
ROUTER --> LAYOUT
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [frontend/src/main.js](file://frontend/src/main.js#L1-L24)
|
||||
- [frontend/src/stores/index.js](file://frontend/src/stores/index.js#L1-L3)
|
||||
- [frontend/src/stores/user.js](file://frontend/src/stores/user.js#L1-L49)
|
||||
- [frontend/src/stores/app.js](file://frontend/src/stores/app.js#L1-L31)
|
||||
- [frontend/src/views/Login.vue](file://frontend/src/views/Login.vue#L1-L155)
|
||||
- [frontend/src/views/Layout.vue](file://frontend/src/views/Layout.vue#L1-L241)
|
||||
- [frontend/src/router/index.js](file://frontend/src/router/index.js#L1-L116)
|
||||
- [frontend/src/api/auth.js](file://frontend/src/api/auth.js#L1-L22)
|
||||
- [frontend/src/api/department.js](file://frontend/src/api/department.js#L1-L32)
|
||||
|
||||
章节来源
|
||||
- [frontend/src/main.js](file://frontend/src/main.js#L1-L24)
|
||||
- [frontend/src/stores/index.js](file://frontend/src/stores/index.js#L1-L3)
|
||||
- [frontend/src/router/index.js](file://frontend/src/router/index.js#L1-L116)
|
||||
|
||||
## 核心组件
|
||||
- 用户状态 Store(user)
|
||||
- 状态:令牌与用户信息
|
||||
- 动作:登录、获取用户信息、登出
|
||||
- 持久化:本地存储令牌
|
||||
- 应用配置 Store(app)
|
||||
- 状态:侧边栏折叠状态、科室树
|
||||
- 动作:切换侧边栏、加载科室树
|
||||
- 统一导出(stores/index.js)
|
||||
- 集中导出各 Store,便于视图层按需引入
|
||||
- 入口与安装(main.js)
|
||||
- 安装 Pinia 插件并挂载到根实例
|
||||
- 路由与鉴权(router/index.js)
|
||||
- 登录页与受保护页面的导航控制
|
||||
- API 层(api/auth.js、api/department.js)
|
||||
- 对后端接口的封装,供 Store 动作调用
|
||||
|
||||
章节来源
|
||||
- [frontend/src/stores/user.js](file://frontend/src/stores/user.js#L1-L49)
|
||||
- [frontend/src/stores/app.js](file://frontend/src/stores/app.js#L1-L31)
|
||||
- [frontend/src/stores/index.js](file://frontend/src/stores/index.js#L1-L3)
|
||||
- [frontend/src/main.js](file://frontend/src/main.js#L1-L24)
|
||||
- [frontend/src/router/index.js](file://frontend/src/router/index.js#L103-L113)
|
||||
- [frontend/src/api/auth.js](file://frontend/src/api/auth.js#L1-L22)
|
||||
- [frontend/src/api/department.js](file://frontend/src/api/department.js#L1-L32)
|
||||
|
||||
## 架构总览
|
||||
以下序列图展示登录流程中,视图层、用户 Store 与 API 层之间的交互,体现异步状态处理与错误反馈。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant V as "Login.vue"
|
||||
participant US as "useUserStore"
|
||||
participant API as "auth.js"
|
||||
participant RT as "router/index.js"
|
||||
V->>US : "login(用户名, 密码)"
|
||||
US->>API : "POST /auth/login"
|
||||
API-->>US : "返回访问令牌"
|
||||
US->>US : "写入令牌到本地存储"
|
||||
US-->>V : "返回登录结果"
|
||||
V->>RT : "跳转至首页"
|
||||
Note over V,RT : "若登录失败,显示错误提示"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [frontend/src/views/Login.vue](file://frontend/src/views/Login.vue#L73-L89)
|
||||
- [frontend/src/stores/user.js](file://frontend/src/stores/user.js#L11-L20)
|
||||
- [frontend/src/api/auth.js](file://frontend/src/api/auth.js#L4-L11)
|
||||
- [frontend/src/router/index.js](file://frontend/src/router/index.js#L103-L113)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### 用户状态 Store(user)
|
||||
- 状态定义
|
||||
- 令牌:用于鉴权,初始化从本地存储读取
|
||||
- 用户信息:当前登录用户的资料
|
||||
- 动作方法
|
||||
- 登录:调用认证接口,成功后写入令牌并持久化
|
||||
- 获取用户信息:拉取当前用户资料
|
||||
- 登出:清空令牌与用户信息,跳转登录页
|
||||
- 最佳实践
|
||||
- 在登录动作中捕获异常并返回布尔值,便于视图层判断
|
||||
- 登出时同步清理本地存储与路由跳转,保证状态一致性
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["进入登录动作"]) --> CallAPI["调用认证接口"]
|
||||
CallAPI --> Success{"请求成功?"}
|
||||
Success --> |是| SetToken["写入令牌到状态与本地存储"]
|
||||
Success --> |否| ReturnFalse["返回失败标记"]
|
||||
SetToken --> Done(["结束"])
|
||||
ReturnFalse --> Done
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [frontend/src/stores/user.js](file://frontend/src/stores/user.js#L11-L20)
|
||||
- [frontend/src/api/auth.js](file://frontend/src/api/auth.js#L4-L11)
|
||||
|
||||
章节来源
|
||||
- [frontend/src/stores/user.js](file://frontend/src/stores/user.js#L1-L49)
|
||||
- [frontend/src/api/auth.js](file://frontend/src/api/auth.js#L1-L22)
|
||||
|
||||
### 应用配置 Store(app)
|
||||
- 状态定义
|
||||
- 侧边栏折叠状态:控制菜单宽度与显示
|
||||
- 科室树:后端返回的树形结构,用于菜单生成
|
||||
- 动作方法
|
||||
- 切换侧边栏:翻转折叠状态
|
||||
- 加载科室树:调用接口获取数据并赋值
|
||||
- 最佳实践
|
||||
- 在加载动作中使用 try/catch 处理异常,避免未捕获错误导致界面卡死
|
||||
- 数据为空时提供兜底逻辑,确保 UI 正常渲染
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["进入加载科室树"]) --> TryCall["调用接口获取数据"]
|
||||
TryCall --> Try{"请求成功?"}
|
||||
Try --> |是| Assign["赋值到状态"]
|
||||
Try --> |否| Catch["记录错误日志"]
|
||||
Assign --> End(["结束"])
|
||||
Catch --> End
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [frontend/src/stores/app.js](file://frontend/src/stores/app.js#L15-L22)
|
||||
- [frontend/src/api/department.js](file://frontend/src/api/department.js#L9-L11)
|
||||
|
||||
章节来源
|
||||
- [frontend/src/stores/app.js](file://frontend/src/stores/app.js#L1-L31)
|
||||
- [frontend/src/api/department.js](file://frontend/src/api/department.js#L1-L32)
|
||||
|
||||
### 视图层集成与跨组件共享
|
||||
- 登录页(Login.vue)
|
||||
- 引入用户 Store,绑定表单校验与加载态
|
||||
- 调用登录动作,根据返回结果进行消息提示与路由跳转
|
||||
- 布局页(Layout.vue)
|
||||
- 引入应用 Store,控制侧边栏折叠与菜单渲染
|
||||
- 引入用户 Store,触发登出动作
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant LV as "Login.vue"
|
||||
participant UV as "useUserStore"
|
||||
LV->>UV : "login()"
|
||||
UV-->>LV : "true/false"
|
||||
LV->>LV : "提示与路由跳转"
|
||||
participant LV2 as "Layout.vue"
|
||||
participant AV as "useAppStore"
|
||||
LV2->>AV : "toggleSidebar()"
|
||||
LV2->>AV : "loadDepartmentTree()"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [frontend/src/views/Login.vue](file://frontend/src/views/Login.vue#L55-L89)
|
||||
- [frontend/src/views/Layout.vue](file://frontend/src/views/Layout.vue#L76-L124)
|
||||
- [frontend/src/stores/user.js](file://frontend/src/stores/user.js#L11-L20)
|
||||
- [frontend/src/stores/app.js](file://frontend/src/stores/app.js#L10-L22)
|
||||
|
||||
章节来源
|
||||
- [frontend/src/views/Login.vue](file://frontend/src/views/Login.vue#L1-L155)
|
||||
- [frontend/src/views/Layout.vue](file://frontend/src/views/Layout.vue#L1-L241)
|
||||
|
||||
### 模块化组织与统一导出
|
||||
- stores/index.js 将各 Store 统一导出,便于视图层按需引入,降低导入分散带来的维护成本
|
||||
- 建议后续可扩展计算属性与插件化注册,进一步增强模块化能力
|
||||
|
||||
章节来源
|
||||
- [frontend/src/stores/index.js](file://frontend/src/stores/index.js#L1-L3)
|
||||
|
||||
### 状态持久化策略
|
||||
- 令牌持久化:登录成功后写入本地存储,刷新页面后仍可保持登录态
|
||||
- 状态持久化建议:
|
||||
- 对于轻量配置(如侧边栏折叠),可仅做内存持久化并在必要时写入本地存储
|
||||
- 对于重要业务数据,优先通过后端接口拉取,前端仅做缓存与回退处理
|
||||
|
||||
章节来源
|
||||
- [frontend/src/stores/user.js](file://frontend/src/stores/user.js#L7-L16)
|
||||
- [frontend/src/stores/app.js](file://frontend/src/stores/app.js#L6-L7)
|
||||
|
||||
### 状态订阅与调试
|
||||
- 订阅:可通过 Pinia 提供的订阅机制监听状态变化,便于调试与副作用处理
|
||||
- 调试:结合浏览器开发工具查看 Store 状态与动作调用链,定位问题
|
||||
- 建议:在开发环境开启严格模式与日志输出,生产环境关闭冗余日志
|
||||
|
||||
(本节为通用指导,不直接分析具体文件)
|
||||
|
||||
### 异步状态处理、错误状态管理与加载状态控制
|
||||
- 异步处理:Store 动作统一使用 async/await,确保调用方能正确等待结果
|
||||
- 错误处理:在动作内部捕获异常并返回明确的结果标识,视图层据此给出反馈
|
||||
- 加载状态:视图层维护加载态变量,在动作执行前后切换,提升用户体验
|
||||
|
||||
章节来源
|
||||
- [frontend/src/views/Login.vue](file://frontend/src/views/Login.vue#L77-L88)
|
||||
- [frontend/src/stores/user.js](file://frontend/src/stores/user.js#L11-L20)
|
||||
- [frontend/src/stores/app.js](file://frontend/src/stores/app.js#L15-L22)
|
||||
|
||||
### 状态重置、合并与迁移策略
|
||||
- 重置:登出时清空令牌与用户信息,恢复初始状态
|
||||
- 合并:加载新数据时先清空旧数据再赋值,避免脏数据残留
|
||||
- 迁移:当后端字段变更时,Store 中提供兼容逻辑或版本化处理,保证向前兼容
|
||||
|
||||
章节来源
|
||||
- [frontend/src/stores/user.js](file://frontend/src/stores/user.js#L34-L39)
|
||||
- [frontend/src/stores/app.js](file://frontend/src/stores/app.js#L15-L22)
|
||||
|
||||
## 依赖关系分析
|
||||
- 入口依赖:main.js 依赖 Pinia 安装,确保全局可用
|
||||
- 视图依赖:Login.vue 依赖 user Store,Layout.vue 依赖 app Store
|
||||
- Store 依赖:user Store 依赖 auth API,app Store 依赖 department API
|
||||
- 路由依赖:router/index.js 依赖本地存储令牌进行鉴权守卫
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
MAIN["main.js"] --> PINIA["Pinia"]
|
||||
LOGIN["Login.vue"] --> USER["useUserStore"]
|
||||
LAYOUT["Layout.vue"] --> APP["useAppStore"]
|
||||
USER --> AUTH["auth.js"]
|
||||
APP --> DEPT["department.js"]
|
||||
ROUTER["router/index.js"] --> TOKEN["localStorage(token)"]
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [frontend/src/main.js](file://frontend/src/main.js#L19-L19)
|
||||
- [frontend/src/views/Login.vue](file://frontend/src/views/Login.vue#L55-L58)
|
||||
- [frontend/src/views/Layout.vue](file://frontend/src/views/Layout.vue#L76-L81)
|
||||
- [frontend/src/stores/user.js](file://frontend/src/stores/user.js#L3-L4)
|
||||
- [frontend/src/stores/app.js](file://frontend/src/stores/app.js#L3-L3)
|
||||
- [frontend/src/router/index.js](file://frontend/src/router/index.js#L106-L108)
|
||||
|
||||
章节来源
|
||||
- [frontend/src/main.js](file://frontend/src/main.js#L1-L24)
|
||||
- [frontend/src/router/index.js](file://frontend/src/router/index.js#L1-L116)
|
||||
- [frontend/package.json](file://frontend/package.json#L11-L20)
|
||||
|
||||
## 性能考量
|
||||
- 状态粒度:将高频更新与低频更新拆分到不同 Store 或状态字段,减少不必要的响应式开销
|
||||
- 异步批处理:对频繁触发的动作进行防抖或节流,避免重复请求
|
||||
- 缓存策略:对只读或稳定数据(如科室树)进行本地缓存,降低网络请求频率
|
||||
- 渲染优化:在视图层避免深层嵌套的响应式对象,尽量扁平化状态结构
|
||||
|
||||
(本节为通用指导,不直接分析具体文件)
|
||||
|
||||
## 故障排查指南
|
||||
- 登录失败
|
||||
- 检查登录动作是否抛出异常并返回布尔值
|
||||
- 核对 API 返回结构与 Store 写入逻辑
|
||||
- 无法跳转
|
||||
- 确认路由守卫逻辑与本地存储令牌状态一致
|
||||
- 侧边栏不生效
|
||||
- 检查 Store 折叠状态与视图绑定是否正确
|
||||
- 科室树不显示
|
||||
- 确认接口返回结构与赋值逻辑一致,必要时添加兜底数据
|
||||
|
||||
章节来源
|
||||
- [frontend/src/stores/user.js](file://frontend/src/stores/user.js#L11-L20)
|
||||
- [frontend/src/router/index.js](file://frontend/src/router/index.js#L103-L113)
|
||||
- [frontend/src/views/Layout.vue](file://frontend/src/views/Layout.vue#L4-L25)
|
||||
- [frontend/src/stores/app.js](file://frontend/src/stores/app.js#L15-L22)
|
||||
|
||||
## 结论
|
||||
本项目基于 Pinia 实现了清晰的用户状态与应用配置状态管理,配合统一导出与路由守卫,形成了模块化、可扩展且易于维护的状态体系。遵循本文的最佳实践与策略,可在保证性能与可维护性的前提下,进一步完善异步处理、错误管理与调试能力。
|
||||
|
||||
## 附录
|
||||
- 关键实现位置参考
|
||||
- 用户登录与登出:[frontend/src/stores/user.js](file://frontend/src/stores/user.js#L11-L39)
|
||||
- 应用配置与菜单加载:[frontend/src/stores/app.js](file://frontend/src/stores/app.js#L15-L22)
|
||||
- 视图层集成示例:[frontend/src/views/Login.vue](file://frontend/src/views/Login.vue#L73-L89)、[frontend/src/views/Layout.vue](file://frontend/src/views/Layout.vue#L76-L124)
|
||||
- 入口与安装:[frontend/src/main.js](file://frontend/src/main.js#L19-L19)
|
||||
- 路由与鉴权:[frontend/src/router/index.js](file://frontend/src/router/index.js#L103-L113)
|
||||
- API 封装:[frontend/src/api/auth.js](file://frontend/src/api/auth.js#L4-L11)、[frontend/src/api/department.js](file://frontend/src/api/department.js#L9-L11)
|
||||
Reference in New Issue
Block a user