React + TypeScript 前端项目代码规范文档
作者:小欣前端实战
本文主要介绍了React + TypeScript 前端项目代码规范文档,帮你建立清晰的架构基线,特别包含反AI味规则,避免过度抽象和冗余代码,让你的前端项目更易维护
适用场景
- 新建 React + TypeScript 前端项目时,作为架构基线
- 代码评审时作为风格门禁
- 重构老旧项目时作为目标规范
- AI 辅助编码时,要求 AI 按此规范输出
一、目录架构(精简版)
project/ ├── docs/ # 设计文档、PRD、代码规范 │ ├── design/ # 页面/模块设计文档 │ ├── code-style/ # 代码规范(本文件) │ └── components/ # 公共组件文档 ├── src/ │ ├── main.tsx # 应用入口 │ ├── main.less # 基础样式(font/box-sizing/body) │ ├── api/ # 全局 API 请求层 │ │ ├── request.ts # 请求客户端(axios 封装) │ │ └── user.ts # 按模块拆分 │ ├── components/ # 跨页面公共组件(条件:≥2 个页面复用) │ │ └── <comp>/ │ │ ├── index.tsx │ │ ├── index.less │ │ └── models.ts │ ├── pages/ # 页面模块 │ │ └── <page>/ │ │ ├── index.tsx # 页面入口:装配主流程 │ │ ├── index.module.less # 页面样式 │ │ ├── api.ts # 页面专属接口 │ │ ├── components/ # 页面内部组件 │ │ ├── hooks/ # 页面 hook │ │ └── view.ts # 表格列/表单 schema 等展示结构 │ ├── services/ # 业务流程层(多接口流程、跨页面用例) │ ├── stores/ # 全局状态 │ ├── models/ # 跨页面共享数据模型 │ ├── lib/ # 纯工具函数(无 React 依赖) │ ├── styles/ # 全局样式 token / 主题变量 │ └── router/ # 路由配置 ├── __tests__/ # 单元测试(镜像 src 结构) └── mock/ # 接口 mock
核心原则:业务实现优先靠近使用场景,确认复用后再上提。
二、命名规范
文件与目录
| 类型 | 规则 | 示例 |
|---|---|---|
| 所有源文件 | kebab-case | incident-reference.ts, user-avatar.tsx |
| 页面目录 | kebab-case,与路由 key 一致 | src/pages/incident-detail/ |
| 组件目录 | kebab-case | src/components/table-list/ |
| 样式文件 | index.less(公共)或 *.module.less(页面) | index.module.less |
| 类型声明 | kebab-case.d.ts | wasm-exec.d.ts |
代码标识符
| 类型 | 规则 | 示例 |
|---|---|---|
| React 组件 | PascalCase | IncidentDetailPage |
| Hook | use 前缀 + camelCase | useIncidentDetail |
| 普通函数 | camelCase,动词开头 | buildQueryParams, formatTimestamp |
| 类型/接口 | PascalCase | IncidentFormModel |
| 常量 | UPPER_SNAKE_CASE 或 camelCase | MAX_FILE_SIZE |
| 事件处理 | on + 名词 + 动词 | onSelectRecord, onConfirmDelete |
三、文件规模约束
| 文件类型 | 上限 | 超出后拆分为 |
|---|---|---|
| 普通 .ts/.tsx | 300 行 | components/, hooks/, utils.ts |
| 页面入口 index.tsx | 500 行 | components/, view.ts |
| 仓储/Store | 600 行 | mapper.ts, selectors.ts, actions.ts |
| .less | 800 行 | 按组件/区块就近拆分 |
四、组件规范
页面入口组件
// ✅ 好的页面入口:装配主流程,不堆细节
function IncidentDetailPage() {
const detail = useIncidentDetail(id);
const { canEdit, isClosed } = detail.state;
return (
<div className={styles.page}>
<IncidentHeader event={detail.event} canEdit={canEdit} />
<IncidentTimeline entries={detail.timeline} />
<IncidentEditModal open={editing} onSubmit={detail.save} />
</div>
);
}
// ❌ 不好的页面入口:堆大段 JSX、表格列、内联逻辑
function IncidentDetailPage() {
return (
<div>
<Table columns={[
{ title: '状态', dataIndex: 'status', render: (v) => {
if (v === 'open') return <Tag color="red">...</Tag>
// ... 80 行 JSX 堆在入口
}}
]}/>
</div>
);
}
Props 约定
- Props 用明确命名的对象类型,不用裸字段散列
- 超过 6 个 props 必须定义显式 Props 类型
- 超过 8 个 props 评估拆分或分组
- 回调超过 3 个时合并为
actions对象 - 透传完整 store/DTO 是反模式——传入组件真正需要的 view model
// ✅ 分组 props
type IncidentHeaderProps = {
event: IncidentView;
actions: {
onEdit: () => void;
onClose: () => void;
onReopen: () => void;
};
};
// ❌ 透传完整 store
type IncidentHeaderProps = {
store: IncidentStore; // 组件不需要整个 store
};
组件拆分原则
- 一个组件只处理一个明确功能点
- 80 行以上 JSX 片段必须拆分
- 不为"可能复用"提前抽象
- 不拆出只转发 props 的薄壳组件
五、业务分层
请求层 (api/) → 只做 HTTP 调用,返回 DTO ↓ 服务层 (services/) → 组合多接口、业务编排 ↓ 状态层 (stores/) → 全局/页面状态管理 ↓ Hook 层 (hooks/) → 临时状态、副作用编排 ↓ 视图层 (pages/components/) → 纯展示和交互入口
分层红线:同一文件不得混放"请求 + 状态 + 渲染"三种职责。
六、反 AI 味规则
这些是 AI 生成代码的常见坏味道,必须避免:
| AI 味 | 人味替代 |
|---|---|
| 冗余空值兜底(data?.result ?? {} || {}) | 按 DTO 定义信任字段,不堆叠兜底 |
| 泛称命名(handleClick, processData, doAction) | 动词+名词+目标(submitCreateForm, toggleAttachmentDelete) |
| 过度抽象(为了"灵活性"加多层 wrapper) | 直接解决问题,确认复用后再提 |
| 无意义注释(// 处理点击事件) | 只写 Why 不写 What,函数名已说明 What |
| 散落 any 类型 | 显式类型或 unknown + 类型守卫 |
| useEffect 里写业务规则 | 业务规则放普通函数/selector,effect 只做副作用编排 |
| 组件内写 API 请求 | 按分层规则——api 层请求,hook/store 触发 |
| div 模拟按钮 | 用 Ant Design Button/Link/Dropdown 等语义组件 |
七、执行路径可读性
函数应像菜谱一样线性可读——输入 → 校验 → 处理 → 输出:
// ✅ 线性可读
async function saveIncident(input: SaveInput) {
const validation = validateSaveInput(input);
if (!validation.ok) return showError(validation);
const payload = buildSavePayload(input);
const result = await requestSave(payload);
return handleSaveResult(result);
}
// ❌ 分支嵌套 + 内联副作用
async function saveIncident(input: SaveInput) {
if (input.name) {
const x = await api.post('/save', { name: input.name }).then(r => {
if (r.data.status === 0) {
message.success('ok');
router.push('/list');
} else {
if (r.data.msg) message.error(r.data.msg);
}
});
}
}
八、样式规则
| 场景 | 方案 |
|---|---|
| 公共组件 | index.less + 全局 class 前缀(如 app-table-*) |
| 页面/布局 | *.module.less,局部作用域 |
| 颜色 | 必须用 token 变量,禁止裸色值 |
| 主题 | 亮/暗色通过 CSS 变量 :root[data-theme="dark"] 切换 |
九、质量门禁
提交前必须通过:
npm run typecheck # tsc --noEmit npm run lint # eslint npm test # 至少覆盖修改文件
- 新增功能必须有对应单元测试
- 修改接口必须同步更新 mock
- PR 描述必须列出改动文件和影响范围
到此这篇关于React + TypeScript 前端项目代码规范文档的文章就介绍到这了,更多相关React TypeScript 代码规范内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
