# 前端开发规范\-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 (
    {users.map(user => ( ))}
); }, (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. 虚拟化:长列表使用虚拟滚动,大数据集使用分页或虚拟表格