Files
obsidian-vault/projects/frontend/frontend-structure-guidelines.md
T

222 lines
6.6 KiB
Markdown
Raw Normal View History

# 前端目录与代码放置规范
> 说明真实分层、目录职责和新增代码放置规则。
---
## 适用范围
单包 Vite + React/Vue + TypeScript 项目。
---
## src 根目录结构
```
src/
├── api/ # 业务接口入口,按领域拆文件并统一导出
├── assets/ # 静态资源占位目录
├── common/ # 站点级常量、配置、静态数据、共享类型
├── components/ # 跨页面复用组件
├── hooks/ # 跨页面复用的 Hooks (React) / Composables (Vue)
├── pages/ # 路由页面
├── router/ # 路由配置
├── styles/ # 全局样式入口
├── utils/ # 通用工具
├── App.tsx # 应用壳 (React 为 .tsx,Vue 为 .vue)
└── main.ts # 启动入口
```
新增目录前先判断能否归入已有层级;不要为了单个文件再造一层。
---
## 各层职责
### `src/api`
用于集中管理接口方法,按业务域拆分,例如:
- `api-user.ts`
- `api-order.ts`
- `api-product.ts`
约束:
- 文件名统一使用 `api-*.ts`
- 所有接口通过 `src/api/index.ts` 暴露
- 页面、组件、Hook 不直接拼 URL 或内联请求逻辑
### `src/common`
放站点级共享数据和基础类型,不放页面局部常量。
典型内容:
- `config.ts`
- `constants.ts`
- `enum.ts`
- `site-data.ts`
- `site-types.ts`
站点级常量、配置、枚举、共享类型优先放此处;可远程获取的数据优先通过 `api/` + 页面 Hooks 获取,不要堆积在 `common/`。
### `src/components`
放多个页面都会复用的通用组件和布局组件。
典型示例:
- `layout-shell.tsx` (React) / `layout-shell.vue` (Vue)
- `nav-header.tsx` / `nav-header.vue`
- `content-card.tsx` / `content-card.vue`
- `loading-state.tsx` / `loading-state.vue`
- `empty-state.tsx` / `empty-state.vue`
- `modal-common.tsx` / `modal-common.vue`
约束:
- 文件名统一使用小写横杠
- 只有跨页面复用的组件才放这里
- 某个页面特有的展示块,优先直接放该页面目录下,避免过早公共化
### `src/hooks`
放跨页面复用的状态与异步逻辑。React 中称为 Hooks,Vue 中称为 Composables。
典型示例:
- `use-promise-data.ts`
- `use-form.ts`
- `use-modal.ts`
- `use-table.ts`
约束:
- 文件名统一使用 `use-*.ts`(React Hooks 和 Vue Composables 均遵循此命名)
- 负责复用逻辑,不负责路由结构和大块 UI 拼装
### `src/pages`
页面层按路由语义组织,一个目录对应一个页面或页面组。
典型结构:
```
pages/
├── home/index.tsx (或 index.vue)
├── list/index.tsx (或 index.vue)
├── list/detail/index.tsx (或 index.vue)
├── admin/index.tsx (或 index.vue)
└── admin/components/admin-table.tsx (或 .vue)
```
约束:
- 路由页面入口统一使用 `index.tsx` (React) 或 `index.vue` (Vue)
- 有明确子路由的页面,使用目录嵌套表达层级,例如 `list/detail/`
- 页面目录名统一使用小写横杠,例如 `order-detail/` 而非 `orderDetail/`
- 仅后台页面共享的组件,放在 `pages/admin/components/`,不要提到全局 `components/`
- 如果未来某个页面出现多个私有组件、Hook、转换函数,可以在该页面目录下新增 `components/`、`hooks/`、`utils/` 子目录;尚未形成稳定模式前,不要预先创建空目录
### `src/router`
集中声明路由和布局装配关系,例如通过 layout route 划分不同壳层。
### `src/utils`
放纯工具函数和请求封装,不承载业务页面状态。
典型文件:
- `request.ts`
- `format.ts`
- `storage.ts`
- `validate.ts`
请求封装、通用工具函数优先放在此处,不要散落到页面或 `api-*` 文件中。
### `src/styles`
全局样式入口和主题变量注入位置。
职责:
- 导入设计变量包 CSS,如 `@your-design-system/tokens/css`
- 全局基础样式、重置样式、通用动画
- 禁止在组件内重复引入设计变量 CSS,统一从 `styles/` 入口注入
### `src/assets`
静态资源占位目录。
职责:
- 存放图片、字体、SVG 等静态文件
- 通过 Vite 自动处理路径引用,禁止手写相对路径拼接到 `public/`
- 单个页面私有的静态资源,优先放在该页面目录下
---
## 命名约定速查
| 类型 | 命名规则 | 示例 | 说明 |
|---|---|---|---|
| 接口文件 | `api-{domain}.ts` | `api-user.ts` | 按业务域拆分,统一从 `index.ts` 导出 |
| Hook/Composable 文件 | `use-{feature}.ts` | `use-form.ts` | React Hooks / Vue Composables 通用命名 |
| 组件文件 | 小写横杠 | `content-card.tsx` / `.vue` | 仅跨页面复用的组件 |
| 页面入口 | `index.tsx` / `index.vue` | `pages/home/index.tsx` | 每个路由页面对应一个入口 |
| 页面目录 | 小写横杠 | `order-detail/` | 有子路由时使用目录嵌套 |
| 工具文件 | 小写横杠 | `format.ts` | 纯函数,不承载业务状态 |
| 样式文件 | 小写横杠 | `index.css` | 全局样式入口 |
---
## 新增代码放置规则
### 新增页面
- 新页面先放到 `src/pages/<route-segment>/index.tsx` (React) 或 `index.vue` (Vue)
- 有详情页或子页时,用子目录表达路由层级
- 页面只负责组装,不要把可复用块全部堆进页面入口文件
### 新增共享组件
满足下面任一条件才放 `src/components/`:
- 至少被两个页面复用
- 明显属于布局壳、空态、加载态、卡片、分页这类跨页面基础组件
否则放到对应页面目录下。
### 新增接口
- 按业务域加到现有 `api-*.ts`,不要为单个接口新建零散文件
- 新增业务域时,才创建新的 `api-<domain>.ts`
- 同步更新 `src/api/index.ts`
### 新增共享数据或类型
- 纯配置、导航、枚举、常量放 `src/common/`
- 类型优先就近放到使用域;只有被多个页面共享时,才进入 `site-types.ts` 或拆新的共享类型文件
---
## 反模式
- 把接口请求直接写进页面组件,绕过 `src/api/`
- 把后台专用页面组件放进全局 `src/components/`
- 为了“看起来规范”预先创建大量空的页面私有 `hooks/`、`utils/`、`components/`
- 把路由层级和目录层级写反,例如把详情页和列表页并列平铺但路由嵌套
- 在 `common/` 堆放只给单页使用的常量或转换函数
---
## 修改前检查
- 这段代码是路由页面、共享组件、共享 Hook/Composable、共享数据,还是接口定义?
- 这个文件未来是否很可能被第二个页面复用?
- 是否应该先并入现有业务域文件,而不是新造目录?
- 是否和 `src/router/` 的路由分组保持一致?