20 KiB
20 KiB
Vue组件开发
**本文引用的文件** - [frontend/src/main.js](file://frontend/src/main.js) - [frontend/package.json](file://frontend/package.json) - [frontend/vite.config.js](file://frontend/vite.config.js) - [frontend/src/App.vue](file://frontend/src/App.vue) - [frontend/src/router/index.js](file://frontend/src/router/index.js) - [frontend/src/views/Layout.vue](file://frontend/src/views/Layout.vue) - [frontend/src/views/Login.vue](file://frontend/src/views/Login.vue) - [frontend/src/stores/app.js](file://frontend/src/stores/app.js) - [frontend/src/stores/user.js](file://frontend/src/stores/user.js) - [frontend/src/api/request.js](file://frontend/src/api/request.js) - [frontend/src/api/department.js](file://frontend/src/api/department.js) - [frontend/src/api/assessment.js](file://frontend/src/api/assessment.js) - [frontend/src/views/basic/Departments.vue](file://frontend/src/views/basic/Departments.vue) - [frontend/src/views/assessment/Assessments.vue](file://frontend/src/views/assessment/Assessments.vue) - [frontend/src/assets/main.scss](file://frontend/src/assets/main.scss)目录
简介
本指南面向使用 Vue 3 Composition API 的前端开发者,结合仓库中的实际代码,系统讲解组件开发的关键实践:响应式数据与生命周期、组件间通信、Element Plus 集成、自定义组件与复用策略、设计模式与代码组织、测试与调试、性能优化以及 API 调用封装与错误处理。文中所有分析均基于仓库中的真实文件与实现。
项目结构
前端采用 Vite + Vue 3 + Pinia + Element Plus 技术栈,路由基于 vue-router,API 层统一通过 axios 封装。整体目录按功能域划分,便于组件与业务模块化组织。
graph TB
A["入口 main.js<br/>创建应用/注册插件"] --> B["根组件 App.vue<br/>国际化配置"]
A --> C["路由 router/index.js<br/>动态导入视图组件"]
A --> D["状态 stores/*<br/>Pinia Store"]
A --> E["API 层 api/*<br/>Axios 封装与接口"]
A --> F["视图 views/*<br/>页面级组件"]
A --> G["样式 assets/main.scss<br/>全局样式与主题变量"]
F --> H["布局 Layout.vue<br/>侧边栏/头部/面包屑"]
F --> I["登录 Login.vue<br/>表单校验/登录流程"]
F --> J["基础数据 Departments.vue<br/>表格/分页/对话框"]
F --> K["考核管理 Assessments.vue<br/>树形筛选/状态标签/批量创建"]
图表来源
- frontend/src/main.js
- frontend/src/App.vue
- frontend/src/router/index.js
- frontend/src/views/Layout.vue
- frontend/src/views/Login.vue
- frontend/src/views/basic/Departments.vue
- frontend/src/views/assessment/Assessments.vue
- frontend/src/stores/app.js
- frontend/src/stores/user.js
- frontend/src/api/request.js
- frontend/src/assets/main.scss
章节来源
核心组件
- 应用入口与插件注册:创建应用实例、注册 Element Plus、图标、Pinia、路由;全局样式引入。
- 根组件:提供 Element Plus 国际化上下文。
- 路由系统:定义页面级路由、懒加载视图、路由守卫(鉴权与标题设置)。
- 状态管理:Pinia Store(应用状态与用户状态),集中管理 token、菜单树、侧边栏折叠等。
- API 层:Axios 实例封装,统一请求/响应拦截器,错误提示与自动登出。
- 视图组件:布局、登录、基础数据、考核管理等页面组件,展示 Composition API 与 Element Plus 的典型用法。
章节来源
- frontend/src/main.js
- frontend/src/App.vue
- frontend/src/router/index.js
- frontend/src/stores/app.js
- frontend/src/stores/user.js
- frontend/src/api/request.js
架构总览
下图展示了从前端入口到页面组件的数据流与交互关系,体现 Composition API、Pinia、Element Plus 与 API 层的协作。
graph TB
subgraph "运行时"
M["main.js<br/>应用初始化"] --> R["router/index.js<br/>路由守卫/导航"]
M --> P["Pinia Stores<br/>useAppStore/useUserStore"]
M --> EP["Element Plus<br/>组件/图标/国际化"]
end
subgraph "页面层"
L["views/Layout.vue<br/>侧边栏/头部/面包屑"]
LG["views/Login.vue<br/>登录表单/消息提示"]
D["views/basic/Departments.vue<br/>表格/分页/对话框"]
A["views/assessment/Assessments.vue<br/>树形筛选/批量创建"]
end
subgraph "数据层"
API["api/request.js<br/>Axios 实例/拦截器"]
DEPT["api/department.js<br/>科室接口"]
ASSESS["api/assessment.js<br/>考核接口"]
end
M --> L
M --> LG
M --> D
M --> A
L --> P
LG --> P
D --> DEPT
A --> ASSESS
DEPT --> API
ASSESS --> API
API --> R
图表来源
- frontend/src/main.js
- frontend/src/router/index.js
- frontend/src/stores/app.js
- frontend/src/stores/user.js
- frontend/src/views/Layout.vue
- frontend/src/views/Login.vue
- frontend/src/views/basic/Departments.vue
- frontend/src/views/assessment/Assessments.vue
- frontend/src/api/request.js
- frontend/src/api/department.js
- frontend/src/api/assessment.js
组件详解
布局组件 Layout.vue
- 功能要点
- 侧边栏菜单:根据后端返回的菜单树渲染,支持折叠切换与图标动态绑定。
- 头部区域:面包屑、用户下拉菜单、登出。
- 内容区:路由视图过渡动画。
- 数据加载:首次挂载时异步加载菜单树,失败时回退默认菜单。
- 关键实现模式
- Composition API:使用 ref、reactive、onMounted 管理状态与生命周期。
- Element Plus:el-menu、el-breadcrumb、el-dropdown、el-icon、el-tree-select 等。
- 状态与 API:Pinia 应用状态用于侧边栏折叠;菜单树通过 API 获取。
- 设计建议
- 菜单树转换逻辑可抽离为工具函数,提升可测试性。
- 错误回退策略需与后端约定默认结构,避免空值处理分散。
flowchart TD
Start(["组件挂载"]) --> Load["加载菜单树"]
Load --> Ok{"请求成功?"}
Ok --> |是| Render["渲染菜单树"]
Ok --> |否| Fallback["使用默认菜单"]
Render --> End(["完成"])
Fallback --> End
图表来源
章节来源
登录组件 Login.vue
- 功能要点
- 用户名/密码输入、表单校验、Enter 键触发登录。
- 登录流程:调用用户 Store 的登录方法,成功后跳转首页,失败提示错误。
- 加载态:按钮 loading 控制防止重复提交。
- 关键实现模式
- 表单校验:Element Plus el-form + validate。
- 消息提示:ElMessage 成功/错误提示。
- 路由跳转:vue-router 的 push。
- 状态管理:Pinia 用户 Store 管理 token 与登录状态。
- 设计建议
- 将表单规则抽取为可复用的验证器,便于多组件共享。
- 登录成功后的回调可抽象为通用钩子,减少重复逻辑。
sequenceDiagram
participant U as "用户"
participant C as "Login.vue"
participant S as "useUserStore"
participant R as "router"
U->>C : 输入用户名/密码并点击登录
C->>C : 表单校验 validate()
alt 校验通过
C->>S : login(username, password)
S-->>C : 返回布尔结果
alt 登录成功
C->>R : push("/")
C->>C : 显示成功消息
else 登录失败
C->>C : 显示错误消息
end
else 校验失败
C->>C : 不发起请求
end
图表来源
章节来源
科室管理组件 Departments.vue
- 功能要点
- 查询条件:关键词、类型、分页参数。
- 表格列:编码、名称、类型(标签)、层级、状态开关、创建时间。
- 操作列:编辑、删除;状态变更即时更新。
- 对话框:新增/编辑表单,树形上级选择、表单校验、提交。
- 分页:el-pagination 支持页大小与当前页变更。
- 关键实现模式
- 表单与表格:Element Plus el-table、el-dialog、el-form、el-tree-select。
- 状态与生命周期:ref/reactive 管理本地状态;onMounted 初始化加载。
- API 调用:封装的部门接口,统一错误处理与消息提示。
- 设计建议
- 将“状态标签映射”与“日期格式化”抽离为纯函数,便于复用与测试。
- 对话框表单校验失败时聚焦首个错误项,提升用户体验。
flowchart TD
Init(["组件挂载"]) --> LoadList["加载科室列表"]
Init --> LoadTree["加载科室树"]
LoadList --> Done["渲染表格"]
LoadTree --> Done
Done --> Search["用户点击查询"]
Search --> LoadList
Done --> Edit["打开编辑对话框"]
Edit --> Submit["提交表单校验"]
Submit --> |通过| Save["调用新增/更新接口"]
Submit --> |失败| Focus["提示并聚焦错误项"]
Save --> Refresh["刷新列表与树"]
Refresh --> Done
图表来源
章节来源
考核管理组件 Assessments.vue
- 功能要点
- 查询条件:所属科室(树形选择)、考核周期(月份)、状态筛选。
- 表格列:姓名、科室、周期、总分、加权得分(带等级样式)、状态标签、创建时间。
- 操作列:详情、提交、审核(通过/驳回)、确认。
- 批量创建:弹窗选择科室、周期、指标集合,构造 URLSearchParams 发起请求。
- 关键实现模式
- 状态映射:状态标签与样式映射,分数等级样式。
- 多源数据:同时加载科室树与有效指标,保证 UI 一致性。
- 批量创建:URLSearchParams 处理重复查询参数,满足后端要求。
- 设计建议
- 将“状态标签映射”与“分数等级样式”抽取为独立工具,便于统一维护。
- 批量创建前进行必填项校验,避免无效请求。
sequenceDiagram
participant U as "用户"
participant C as "Assessments.vue"
participant API as "assessment.js"
participant REQ as "request.js(Axios)"
participant R as "router"
U->>C : 点击“批量创建”
C->>C : 打开弹窗并清空表单
U->>C : 填写科室/周期/指标
C->>C : 校验必填项
alt 校验通过
C->>API : batchCreateAssessments(data)
API->>REQ : POST /assessments/batch-create<br/>构造URLSearchParams
REQ-->>API : 返回结果
API-->>C : 结果
C->>C : 显示成功消息并关闭弹窗
C->>C : 刷新列表
else 校验失败
C->>C : 显示提示
end
U->>C : 点击“详情”
C->>R : push(/assessments/ : id)
图表来源
- frontend/src/views/assessment/Assessments.vue
- frontend/src/api/assessment.js
- frontend/src/api/request.js
- frontend/src/router/index.js
章节来源
状态管理与生命周期
- 应用状态(useAppStore)
- 管理侧边栏折叠状态与科室树数据,提供切换与加载方法。
- 用户状态(useUserStore)
- 管理 token、用户信息、登录/登出流程;登出后清理本地存储并跳转登录页。
- 生命周期
- 页面组件普遍在 onMounted 中发起初次数据加载;对话框打开时再加载必要数据(如树形选择)。
章节来源
- frontend/src/stores/app.js
- frontend/src/stores/user.js
- frontend/src/views/Layout.vue
- frontend/src/views/basic/Departments.vue
- frontend/src/views/assessment/Assessments.vue
组件间通信与路由集成
- Props 与事件
- Element Plus 组件通过 v-model、事件(如 size-change、current-change)实现双向绑定与回调。
- 插槽与作用域插槽
- 表格列使用作用域插槽渲染标签、状态与格式化字段。
- 路由与导航
- 路由守卫统一处理登录态与页面标题;详情页通过动态路由参数跳转。
章节来源
Element Plus 集成与自定义组件
- 全局注册图标与组件
- 在入口循环注册 Element Plus 图标,按需在组件中使用。
- 国际化与主题
- 根组件提供语言包;全局样式定义主题变量与通用组件样式。
- 自定义组件开发建议
- 将常用交互(如弹窗、树形选择、状态标签)封装为可复用组件,统一 props 与事件。
- 保持组件单一职责,通过插槽扩展内容。
章节来源
API 调用封装与错误处理
- Axios 实例
- 统一 base URL、超时、请求头;自动注入 Authorization。
- 响应拦截
- 统一处理业务错误码、HTTP 状态码;401 自动清除 token 并跳转登录。
- 接口封装
- 按领域拆分接口文件(部门、考核),对特殊参数(如批量创建)进行 URLSearchParams 处理。
sequenceDiagram
participant C as "组件"
participant API as "api/*"
participant AX as "request.js(Axios)"
participant BE as "后端"
C->>API : 调用接口函数
API->>AX : request.get/post/put/delete(...)
AX->>BE : 发送请求(携带token)
BE-->>AX : 返回响应
AX->>AX : 响应拦截器校验
alt 业务成功
AX-->>API : 返回数据
API-->>C : 返回结果
else 业务失败/HTTP异常
AX-->>API : 抛出错误并提示
API-->>C : 捕获错误
end
图表来源
章节来源
依赖关系分析
- 运行时依赖
- Vue 3、vue-router、pinia、axios、element-plus、@element-plus/icons-vue、echarts、dayjs。
- 构建与开发
- Vite、@vitejs/plugin-vue、sass。
- 代理与别名
- Vite 代理 /api -> 后端 8000 端口;路径别名 @ 指向 src。
graph LR
P["package.json 依赖"] --> V["Vue 3"]
P --> R["vue-router"]
P --> S["pinia"]
P --> X["axios"]
P --> EP["element-plus"]
P --> I["@element-plus/icons-vue"]
P --> E["echarts"]
P --> D["dayjs"]
VC["vite.config.js"] --> A["@ 路径别名"]
VC --> PX["/api 代理"]
图表来源
章节来源
性能考量
- 组件渲染
- 使用 v-loading 在长列表加载时提供占位反馈,避免白屏。
- 表格列使用作用域插槽渲染标签与状态,减少重复计算。
- 状态与计算
- 将映射表(状态/类型)定义为常量,避免每次渲染重新创建。
- 网络请求
- 合理使用分页参数,避免一次性加载过多数据。
- 批量创建时使用 URLSearchParams,确保后端高效处理。
- 资源加载
- 图标与组件按需使用,避免不必要的全局注册导致体积增大。
故障排查指南
- 登录失败
- 检查用户 Store 的登录接口是否正确返回 token;确认本地存储是否写入。
- 路由守卫是否正确拦截未登录访问。
- 菜单加载失败
- 确认后端菜单树接口返回结构;组件中是否有默认回退逻辑。
- 表单校验不生效
- 确认 el-form 的 ref 与 validate 调用时机;rules 是否正确绑定。
- 401 自动登出
- 检查响应拦截器是否正确识别 401 并清除 token 与跳转登录。
- 批量创建失败
- 确认 URLSearchParams 的重复参数构造是否符合后端期望。
章节来源
- frontend/src/stores/user.js
- frontend/src/router/index.js
- frontend/src/views/Layout.vue
- frontend/src/api/request.js
- frontend/src/api/assessment.js
结论
本项目以 Vue 3 Composition API 为核心,结合 Pinia、Element Plus 与 axios 封装,形成了清晰的页面组件、状态管理与 API 层分工。通过统一的错误处理与路由守卫,提升了系统的稳定性与可用性。建议在后续迭代中进一步抽取可复用组件与工具函数,完善单元测试与端到端测试,持续优化性能与可维护性。
附录
- 命名规范建议
- 组件文件:PascalCase(如 Departments.vue)。
- Store:useXxxStore(如 useUserStore)。
- API 函数:动词+名词(如 getAssessments、createDepartment)。
- 常量:UPPER_SNAKE_CASE(如 STATUS_MAP)。
- 代码组织建议
- 按功能域划分 views、stores、api,避免交叉耦合。
- 将样式与主题变量集中在 assets/main.scss,统一风格。
- 测试与调试
- 使用 Vitest/Jest 编写组件与工具函数测试;利用浏览器 DevTools 与 Vue DevTools 调试响应式数据与生命周期。