# 前端开发规范\-React篇
React 开发实践指南
V1\.0 \| 2026年5月 \
# 一、概述与总则
本文档旨在统一前端开发团队的技术实践标准,确保代码质量、可维护性和团队协作效率。规范覆盖 React 技术栈的核心开发场景,同时涵盖 HTML/CSS、JavaScript/TypeScript 等基础层面的通用准则。
## 1\.1 适用范围
本规范适用于所有使用 React 技术栈的前端项目,包括但不限于:
1. 使用 React 18\+ 的 Web 应用项目
2. 基于 Next\.js、Remix 等元框架的服务端渲染项目
3. 使用 React Native 的移动端跨平台项目(部分适用)
## 1\.2 规范层级
规范条目按强制程度分为三个层级,开发者应根据项目实际情况合理遵循:
|**层级**|**标识**|**说明**|
|---|---|---|
|必须(Must)|\[M\]|所有项目必须严格遵守,Code Review 中必检项|
|推荐(Should)|\[S\]|强烈建议遵循,特殊场景经评估后可调整|
|可选(May)|\[O\]|根据项目实际情况选择性采纳|
## 1\.3 技术栈版本要求
新项目应优先采用以下技术栈版本,已有项目应在迭代周期内逐步升级:
|**技术项**|**推荐版本**|**说明**|
|---|---|---|
|React|18\.x / 19\.x|使用最新稳定版|
|TypeScript|5\.5\+|strict 模式启用|
|Vite|6\.x|构建工具首选|
|Next\.js|15\.x|SSR/SSG 场景|
|Tailwind CSS|4\.x|原子化 CSS 方案|
|ESLint|9\.x|Flat Config 格式|
# 二、React 开发规范
React 是本规范的核心关注领域。本章从组件设计、Hooks 使用、状态管理、TypeScript 类型约束和性能优化五个维度,系统性地定义 React 开发的最佳实践。
## 2\.1 组件设计规范
### 2\.1\.1 组件分类与组织
React 组件应按职责明确划分为以下类别,并在项目目录中保持清晰的组织结构:
|**组件类型**|**存放路径**|**职责说明**|
|---|---|---|
|Page 组件|app/ 或 pages/|路由级别的页面组件,负责数据获取和页面级布局|
|Layout 组件|components/layout/|页面布局框架,如 Header、Sidebar、Footer|
|UI 组件|components/ui/|基础 UI 元素,Button、Input、Modal 等纯展示组件|
|Feature 组件|features/\*/components/|业务功能组件,与特定功能域紧耦合|
|HOC / 工具|components/hoc/|高阶组件和渲染工具(render props)|
### 2\.1\.2 函数组件优先
自 React 16\.8 引入 Hooks 以来,函数组件已成为官方推荐的标准写法。所有新开发组件必须使用函数组件,类组件仅在维护遗留代码时允许存在。
```TypeScript
// 推荐:函数组件 + Hooks
import { useState, useCallback } from 'react';
interface UserCardProps {
user: User;
onSelect: (id: string) => void;
}
export function UserCard({ user, onSelect }: UserCardProps) {
const [expanded, setExpanded] = useState(false);
const handleClick = useCallback(() => {
onSelect(user.id);
setExpanded(prev => !prev);
}, [onSelect, user.id]);
return (
{user.name}
{expanded && }
);
}
```
### 2\.1\.3 Props 设计原则
组件的 Props 接口设计直接影响组件的可复用性和可维护性。遵循以下原则:
4. 单一职责:每个组件只接收其渲染所需的最小数据集合,避免传递冗余数据
5. 显式接口:使用 TypeScript interface 定义 Props,禁止隐式 any 类型
6. 默认值策略:对可选 Props 提供合理的默认值,或使用解构赋值简化处理
7. 事件命名:自定义事件处理器以 on 为前缀(如 onSelect、onValueChange),遵循 React 原生事件命名惯例
8. 避免过度透传:不要简单地将父组件的 Props 全部展开传递给子组件,应显式声明所需属性
### 2\.1\.4 组件文件结构
每个组件应按以下结构组织,确保关注点分离和可测试性:
```TypeScript
// components/UserCard/index.tsx
export { UserCard } from './UserCard';
export type { UserCardProps } from './types';
// components/UserCard/UserCard.tsx
import { useState } from 'react';
import type { UserCardProps } from './types';
import { useUserCard } from './useUserCard';
import * as S from './styles';
export function UserCard({ user, onSelect }: UserCardProps) {
const { expanded, handleClick } = useUserCard(user, onSelect);
return (
...
);
}
// components/UserCard/types.ts
export interface UserCardProps {
user: User;
onSelect: (id: string) => void;
}
// components/UserCard/useUserCard.ts
export function useUserCard(user: User, onSelect: (id: string) => void) {
// 业务逻辑抽离到自定义 Hook
}
// components/UserCard/styles.ts (styled-components / CSS Modules)
```
## 2\.2 Hooks 使用规范
### 2\.2\.1 Hooks 基础规则
Hooks 是 React 16\.8 引入的革命性特性,必须严格遵循以下使用规则,否则可能导致不可预期的行为:
9. 只在最顶层调用 Hooks:不要在循环、条件判断或嵌套函数中调用 Hooks
10. 只在 React 函数中调用 Hooks:在函数组件或自定义 Hook 中调用,不要在普通 JavaScript 函数中调用
11. 以 use 开头命名:自定义 Hook 必须以 use 开头命名,以便 ESLint 插件识别
12. 依赖数组诚实原则:useEffect、useMemo、useCallback 的依赖数组必须完整列出所有依赖项
### 2\.2\.2 useEffect 最佳实践
useEffect 是最常用的 Hook 之一,也是最容易滥用的。遵循以下实践:
```JavaScript
// 推荐:单一职责的 Effect
useEffect(() => {
const controller = new AbortController();
fetchUser(userId, { signal: controller.signal })
.then(setUser)
.catch(setError);
return () => controller.abort();
}, [userId]); // 依赖数组必须完整
// 推荐:逻辑拆分到独立 Effect
useEffect(() => {
// 数据获取逻辑
}, [params]);
useEffect(() => {
// DOM 操作或订阅逻辑
return () => { /* 清理逻辑 */ };
}, []);
// 禁止:缺失依赖项
useEffect(() => {
fetchData(page); // page 未在依赖数组中!
}, []); // eslint-disable-line 是临时方案,应尽快修复
```
### 2\.2\.3 useMemo 与 useCallback
性能优化 Hooks 应在有明确性能问题时使用,避免过早优化。遵循以下准则:
13. useMemo:用于缓存昂贵的计算结果,仅在计算成本显著高于缓存开销时使用
14. useCallback:用于缓存事件处理函数,主要配合 React\.memo 使用,避免子组件不必要的重渲染
15. 避免滥用:简单的计算和事件处理不需要 memoization,React 的渲染性能通常优于预期
16. 依赖数组完整性:与 useEffect 同样,必须确保依赖数组的完整性
```JavaScript
// 推荐:复杂数据转换使用 useMemo
const filteredUsers = useMemo(() => {
return users
.filter(u => u.active)
.sort((a, b) => b.score - a.score)
.slice(0, 100);
}, [users]);
// 推荐:配合 React.memo 使用 useCallback
const handleSubmit = useCallback((values: FormData) => {
api.submit(values).then(onSuccess);
}, [onSuccess]);
// 禁止:对简单值使用 useMemo
const fullName = useMemo(
() => `$${firstName} $${lastName}`,
[firstName, lastName] // 字符串拼接成本极低,无需缓存
);
```
## 2\.3 状态管理规范
### 2\.3\.1 状态管理策略
React 应用的状态管理应按状态的作用域和复杂度选择适当的方案,避免过度工程化:
|**状态类型**|**管理方案**|**适用场景**|
|---|---|---|
|本地 UI 状态|useState|组件内部的临时状态,如表单输入、展开/收起|
|派生状态|useMemo / 计算|可从已有状态计算得出的值|
|共享状态|Context / Props|跨 2\-3 层组件传递的状态|
|全局状态|Zustand / Jotai|应用级共享状态,如用户信息、主题设置|
|服务端状态|TanStack Query|服务器数据缓存和同步|
|表单状态|React Hook Form|复杂表单的状态和验证管理|
### 2\.3\.2 Context 使用规范
React Context 适用于跨组件层级的数据传递,但不当使用会导致性能问题:
17. 拆分 Context:将高频变化和低频变化的状态拆分到独立的 Context,避免不必要的重渲染
18. 避免过度使用:仅在真正需要跨多级组件传递数据时使用,简单的父子组件通信仍应通过 Props
19. 结合 useReducer:对于复杂状态逻辑,Context 配合 useReducer 可以实现轻量级的 Redux\-like 方案
```TypeScript
// 推荐:拆分 Context 避免重渲染
const ThemeContext = createContext('light');
const UserContext = createContext(null);
// ThemeProvider 更新时,只消费 ThemeContext 的组件重渲染
// UserProvider 更新时,只消费 UserContext 的组件重渲染
// 推荐:Context + useReducer 组合
type Action = { type: 'increment' } | { type: 'decrement' };
const CounterContext = createContext<{
state: number;
dispatch: React.Dispatch;
} | null>(null);
```
### 2\.3\.3 外部状态管理(Zustand/Jotai)
对于中大型企业级应用,推荐使用轻量级的原子化状态管理方案,如 Zustand 或 Jotai:
20. Zustand:适合模块化的 Store 架构,API 极简,无 Provider 包裹问题
21. Jotai:适合原子化的细粒度状态管理,状态依赖自动追踪
22. 避免 Redux 过度使用:仅在需要 Redux DevTools 时间旅行调试、复杂中间件链时考虑 Redux Toolkit
## 2\.4 TypeScript 类型规范
### 2\.4\.1 组件 Props 类型
所有组件 Props 必须使用 TypeScript 接口显式定义,禁止使用 any 类型绕过类型检查:
```TypeScript
// 推荐:显式 Props 接口
interface ButtonProps {
variant?: 'primary' | 'secondary' | 'ghost';
size?: 'sm' | 'md' | 'lg';
disabled?: boolean;
loading?: boolean;
onClick?: (event: React.MouseEvent) => void;
children: React.ReactNode;
}
export function Button({
variant = 'primary',
size = 'md',
disabled = false,
loading = false,
onClick,
children,
}: ButtonProps) {
// 实现...
}
// 禁止:隐式 any 或缺少类型
// function Button(props) { // 错误!props 为 any
// return ;
// }
```
### 2\.4\.2 泛型组件
对于数据展示类组件,使用泛型实现类型安全的通用组件:
```TypeScript
// 推荐:泛型表格组件
interface DataTableProps {
data: T[];
columns: ColumnDef[];
keyExtractor: (item: T) => string;
onRowClick?: (item: T) => void;
}
export function DataTable({
data, columns, keyExtractor, onRowClick,
}: DataTableProps) {
return (
{data.map(item => (
onRowClick?.(item)}>
{columns.map(col => (
| {col.render(item)} |
))}
))}
);
}
```
### 2\.4\.3 事件类型
React 事件处理函数应使用 React 提供的泛型事件类型,而非原生 DOM 事件类型:
|**事件类型**|**React 类型**|
|---|---|
|点击事件|React\.MouseEvent\|
|输入事件|React\.ChangeEvent\|
|表单提交|React\.FormEvent\|
|键盘事件|React\.KeyboardEvent\|
|拖拽事件|React\.DragEvent\|
|触摸事件|React\.TouchEvent\|
|通用事件|React\.SyntheticEvent|
## 2\.5 性能优化规范
### 2\.5\.1 渲染优化
React 的渲染优化应从以下维度系统化地进行:
23. React\.memo:对纯展示组件使用 React\.memo 进行浅比较优化,避免不必要的重渲染
24. useMemo / useCallback:对昂贵的计算和传递给子组件的回调进行缓存
25. 虚拟列表:长列表使用 react\-window 或 react\-virtualized 实现虚拟滚动
26. 代码分割:使用 React\.lazy \+ Suspense 实现路由级别和组件级别的懒加载
```JavaScript
// 推荐:React.memo + 自定义比较函数
export const UserList = React.memo(function UserList({
users,
onSelect,
}: UserListProps) {
return (
);
}, (prev, next) => prev.users === next.users);
// 推荐:React.lazy 代码分割
const Dashboard = React.lazy(() => import('./Dashboard'));
const Settings = React.lazy(() => import('./Settings'));
function App() {
return (
}>
} />
} />
);
}
```
### 2\.5\.2 状态更新优化
状态更新方式直接影响渲染性能,应遵循以下最佳实践:
27. 批量更新:React 18 自动批处理所有状态更新,无需手动合并
28. 不可变数据:始终使用不可变更新模式,配合 useMemo/React\.memo 进行引用比较
29. 状态拆分:将独立变化的状态拆分为多个 useState,避免不必要的联合更新
30. 派生状态:优先使用 useMemo 计算派生状态,避免在状态中存储可计算的值
# 三、HTML/CSS 规范
HTML 和 CSS 是前端开发的基础,良好的标记和样式实践是构建可维护应用的前提。
## 3\.1 HTML 语义化
语义化的 HTML 不仅有利于可访问性(A11y),也有助于 SEO 和代码的可读性:
31. 使用恰当的语义化标签:header、nav、main、article、section、aside、footer
32. 表单元素必须关联 label,使用 aria\-label 或 aria\-labelledby 补充描述
33. 图片必须提供有意义的 alt 文本,装饰性图片使用 alt=""
34. 遵循标题层级顺序(h1 → h2 → h3),不要跳级使用
## 3\.2 CSS 架构
推荐采用CSS Modules,避免全局命名空间污染:
```JavaScript
// 推荐:CSS Modules
import styles from './Button.module.css';
export function Button({ children }) {
return ;
}
/* Button.module.css */
.button {
padding: 8px 16px;
border-radius: 4px;
background: var(--color-primary);
color: white;
}
.button:hover {
background: var(--color-primary-dark);
}
```
## 3\.3 响应式设计
所有界面必须适配至少三种断点,采用移动优先的设计策略:
|**断点名**|**尺寸范围**|**适配策略**|
|---|---|---|
|Mobile|\< 768px|单列布局、触摸友好的交互、简化导航|
|Tablet|768px \- 1024px|双列布局、侧边栏可收起、适配触控|
|Desktop|\> 1024px|完整多列布局、 hover 交互、固定侧边栏|
# 四、JavaScript/TypeScript 通用规范
除 React 特定规范外,团队应遵循以下 JavaScript/TypeScript 通用编码规范。
## 4\.1 命名规范
35. 文件名:PascalCase 用于组件文件(UserCard\.tsx),camelCase 用于工具文件(formatDate\.ts)
36. 组件名:PascalCase,与文件名保持一致
37. Hook 名:以 use 开头,后跟 PascalCase(useUserData)
38. 常量:UPPER\_SNAKE\_CASE(MAX\_RETRY\_COUNT)
39. 布尔变量:使用 is、has、should 等前缀(isLoading、hasError)
## 4\.2 代码风格
统一使用 ESLint \+ Prettier 进行代码格式化和质量检查,配置文件纳入版本控制:
```Java
// .eslintrc.cjs
module.exports = {
extends: [
'eslint:recommended',
'@typescript-eslint/recommended',
'plugin:react-hooks/recommended',
],
rules: {
'@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/explicit-function-return-type': 'warn',
'react-hooks/exhaustive-deps': 'error',
},
};
// .prettierrc
{
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "all"
}
```
## 4\.3 类型安全
40. strict 模式:TypeScript 配置必须启用 strict: true
41. 禁止 any:原则上禁止使用 any 类型,必要时应使用 unknown 并配合类型收窄
42. 返回值类型:公共函数应显式声明返回值类型,利用类型推断的边界情况除外
43. 类型导出:组件 Props 接口应随组件一起导出,便于复用
# 五、工程化与项目结构
良好的项目结构和工程化配置是团队协作的基石。
## 5\.1 目录结构
推荐采用以下目录组织方式,Feature\-based 结构优先:
```Python
src/
├── app/ # 路由页面(Next.js / React Router)
│ ├── layout.tsx
│ ├── page.tsx
│ └── dashboard/
│ └── page.tsx
├── components/ # 共享组件
│ ├── ui/ # 基础 UI 组件(Button, Input, Modal)
│ └── layout/ # 布局组件(Header, Sidebar, Footer)
├── features/ # 功能模块
│ └── auth/ # 认证功能
│ ├── api/ # API 请求
│ ├── components/ # 功能组件
│ ├── hooks/ # 功能 Hooks
│ ├── stores/ # 状态管理
│ └── types.ts # 功能类型
├── hooks/ # 全局共享 Hooks
├── lib/ # 工具库和配置
│ ├── api.ts # Axios 实例配置
│ └── utils.ts # 通用工具函数
├── types/ # 全局类型定义
└── styles/ # 全局样式和主题配置
```
## 5\.2 开发工作流
44. Git 分支策略:采用 Git Flow 或 Trunk\-based 开发,功能分支命名格式 feature/描述 或 fix/描述
45. 代码审查:所有代码变更必须通过 Pull Request 审查,至少 1 人 approving 后方可合并
46. 提交规范:遵循 Conventional Commits 规范(feat:、fix:、docs:、refactor:、test: 等前缀)
47. CI/CD:集成自动化测试、代码质量检查(ESLint、TypeScript 编译检查)到 CI 流水线
# 六、性能优化与最佳实践
性能优化是前端开发的重要环节,应贯穿整个开发周期。
## 6\.1 加载性能
48. 资源压缩:启用 Gzip/Brotli 压缩,图片使用 WebP/AVIF 格式
49. 懒加载:路由、图片、非首屏组件均使用懒加载策略
50. 预加载:对关键资源使用 rel=preload,对后续路由使用 rel=prefetch
51. Bundle 分析:定期使用 @next/bundle\-analyzer 或 webpack\-bundle\-analyzer 分析打包体积
## 6\.2 运行时性能
52. 避免频繁的状态更新:使用防抖(debounce)和节流(throttle)控制高频事件
53. Web Workers:将复杂计算 offload 到 Web Worker,避免阻塞主线程
54. 内存管理:及时清理定时器、事件监听器和订阅,防止内存泄漏
55. 虚拟化:长列表使用虚拟滚动,大数据集使用分页或虚拟表格