first commit

This commit is contained in:
xiang
2026-07-25 23:45:09 +08:00
commit c7bd957e6f
47 changed files with 3870 additions and 0 deletions
+107
View File
@@ -0,0 +1,107 @@
# Vue 架构与职责边界
## 目录
- 结构原则
- 组件边界
- Composable
- Pinia
- Vue Router
- API 与数据边界
- 表单
- SSR 与 Hydration
- 依赖和公共 API
- 官方依据
## 结构原则
- 先遵循现有目录结构;不要在单个需求中引入第二套架构。
- 新建中大型项目或独立业务域时,优先按 feature/domain 聚合页面、组件、composable、store、服务和类型;将真正跨域的稳定能力放入 `shared`
- 避免把 `components/``utils/``types/` 变成无边界仓库。目录名需表达所属业务或技术职责。
- 只允许单向依赖:应用层可依赖共享层,共享层不得反向依赖具体页面或业务域。
- 在浏览器、服务端、存储、网络和第三方 SDK 边界建立适配层,避免组件直接承载协议细节。
## 组件边界
- 让页面组件负责路由级编排,让业务组件负责明确用例,让基础组件负责可复用交互和展示。
- 组件同时承担数据请求、复杂业务计算、多块无关 UI 和跨域副作用时,按职责拆分。
- 不按行数机械拆分;仅在职责、复用、测试隔离或性能边界更清晰时提取。
- 保持公共组件 API 小而稳定。避免大量布尔 props 组合出互斥模式;使用判别联合、variant 或具名 slots。
- 不让父组件通过 DOM 查询或 template ref 修改子组件内部状态。
- 向下传递少量明确数据;深层跨树依赖使用 provide/inject 时定义 typed injection key,并提供缺失依赖处理。
- 设计组件时覆盖默认、loading、empty、error、disabled 和只读等适用状态。
## Composable
- composable 封装可复用的有状态逻辑、生命周期或外部系统连接,不把纯函数包装成 composable。
- 接收明确参数或响应式输入;不要隐式读取任意全局单例,除非该依赖就是契约的一部分。
- 返回稳定、最小的公开 API。将 state 与操作区分清楚,必要时返回 readonly state。
- 由创建资源的一方负责释放资源;在内部注册 cleanup,或向调用方暴露明确 `stop`/`dispose`
- 避免一个 composable 同时处理请求、表单、路由、通知和持久化;按用例编排更小能力。
- 对有宿主组件依赖的 composable 标明生命周期约束;纯响应式 composable 应可直接单测。
## Pinia
- 仅将跨组件、跨页面、需持久化或需 DevTools 跟踪的状态放入 store。
- 每个 store 表达一个稳定业务域,使用唯一 id,并在独立文件定义。
- state 保持最小;派生值使用 getters/computed;状态改变和业务动作通过 actions 或明确方法完成。
- 不在组件外随意解构 store;在组件中用 `storeToRefs` 解构响应式 state/gettersactions 可直接解构。
- setup store 必须返回所有应被 Pinia 管理的 state;不要依赖“私有 state”技巧破坏 SSR、DevTools 或插件行为。
- 不在 store 中保存 Router/Route、DOM 元素或不可序列化第三方实例;这些依赖留在调用层或适配层。
- 持久化仅保存必要字段,并处理版本迁移、过期、隐私与反序列化失败。
- 测试 store 的公开 action、getter 和状态转移,不依赖内部实现顺序。
## Vue Router
- 页面级组件使用动态 import 做路由懒加载;不要把异步组件与路由懒加载混为一谈。
- 优先命名路由,集中定义 path、name 和 meta 类型。
- 将认证、权限和通用重定向放在合适的全局或路由级 guard;不要把所有页面业务塞入全局 guard。
- guard 返回导航结果或抛出可处理错误;避免多次调用导航、隐式 fall-through 和未处理竞态。
- 客户端路由权限只控制体验,不构成安全边界;后端必须独立授权。
- 路由参数和 query 都是不可信字符串输入,使用前解析、校验并处理缺失或重复值。
- 编程式导航需要时等待结果并处理 navigation failure。
## API 与数据边界
- 将 HTTP 客户端配置、认证头、错误归一化和序列化放入 API 基础层。
- 按业务域定义 service/repository 函数,组件不直接拼接重复 URL 或处理底层响应结构。
- 为请求参数和响应 DTO 提供类型;对不可信响应在运行时校验关键字段。
- 在边界将 DTO 映射为前端领域模型,避免蛇形命名、nullable 约定和后端枚举扩散到整个 UI。
- 支持请求取消或过期响应丢弃;切页、快速搜索和重复提交必须处理竞态。
- 对 mutation 提供重复提交保护、幂等策略或清晰恢复方式。
- 不在客户端持有服务端密钥。`VITE_*` 内容会进入客户端 bundle,只能存放公开配置。
- 将用户可见错误转换为可行动信息,同时保留脱敏的诊断上下文。
## 表单
- 分离原始 DTO、可编辑表单值、验证结果和提交 payload。
- 明确字段 touched、dirty、validating、disabled 和 submitting 状态。
- 客户端验证用于即时反馈,服务端仍是最终业务校验来源。
- 服务端字段错误映射回对应控件,并提供表单级错误摘要或焦点移动。
- 避免 watcher 组成不可追踪的双向同步链;建立单一数据源和显式 reset/submit 流程。
- 离开页面可能丢失编辑内容时,按需求提供确认或草稿策略。
## SSR 与 Hydration
- 先识别项目是否为 Nuxt、SSR、SSG 或纯 SPA,再选择数据获取和生命周期位置。
- 不在服务端共享请求级可变单例,避免用户间状态泄漏。
- 将浏览器 API 放在客户端生命周期或带环境判断的适配层。
- 保证服务端与首次客户端渲染结构一致;时间、随机数、locale 和设备判断需避免 hydration mismatch。
- setup store、持久化插件和请求缓存必须符合项目 SSR 约定。
## 依赖和公共 API
- 新增依赖前证明现有能力不足,并评估体积、维护状态、类型、许可证、SSR 和 tree-shaking。
- 不因单个小功能引入大型工具库。
- 公共组件、composable、store 和类型一旦被多个模块使用,即视为契约;修改时检查全部调用方并补充回归测试。
- 删除或重命名公共导出前,先迁移调用方并确认兼容策略。
## 官方依据
- [Vue Composables](https://vuejs.org/guide/reusability/composables.html)
- [Vue 状态管理](https://vuejs.org/guide/scaling-up/state-management.html)
- [Pinia:定义 Store](https://pinia.vuejs.org/core-concepts/)
- [Vue Router:懒加载路由](https://router.vuejs.org/guide/advanced/lazy-loading.html)
- [Vue Router:导航守卫](https://router.vuejs.org/guide/advanced/navigation-guards.html)
- [Vite 环境变量与模式](https://vite.dev/guide/env-and-mode)