更新技术栈文档,新增TanStack Query和Sentry组件,优化项目结构说明,添加关于兼容性和工程化的详细信息。

This commit is contained in:
乘风
2025-12-09 11:11:53 +08:00
parent 1be091522e
commit 1ca2ca7058
2 changed files with 776 additions and 1 deletions

View File

@@ -0,0 +1,767 @@
# React 代码编写规范大全
> 参考来源:[React 代码编写规范大全:从基础到架构,打造可维护的企业级应用](https://blog.csdn.net/qq_16242613/article/details/150996674)
编写 React 代码不仅仅是让功能跑起来,更重要的是保证代码的可读性、可维护性和团队协作效率。一套良好的编码规范是达成这些目标的基石。
本文将从**基础规范**、**组件设计**、**状态管理**、**样式处理**、**性能优化**和**项目架构**六个层次,由浅入深地详解 React 的代码编写规范。
---
## 📋 目录
- [一、核心六层规范架构](#一核心六层规范架构)
- [二、L1 - 基础与核心规范](#二l1---基础与核心规范)
- [三、L2 - 组件设计模式](#三l2---组件设计模式)
- [四、L3 - 状态管理规范](#四l3---状态管理规范)
- [五、L4 - 样式与CSS策略](#五l4---样式与css策略)
- [六、L5 - 性能优化指南](#六l5---性能优化指南)
- [七、L6 - 项目结构与架构](#七l6---项目结构与架构)
---
## 一、核心六层规范架构
React 代码规范的六个核心层次,构成了一个完整、健壮的应用开发体系:
```
React 代码规范六层体系
├── L1: 基础与核心规范 (命名、文件组织、JSX、PropTypes)
│ └── 目标: 代码一致性与可读性
├── L2: 组件设计模式 (组件拆分、组合、解耦)
│ └── 目标: 可复用与可维护性
├── L3: 状态管理规范 (State原则、Reducer、Context、Redux)
│ └── 目标: 数据流清晰与可预测
├── L4: 样式与CSS策略 (CSS Modules、Styled-Components、方案选型)
│ └── 目标: 样式可控与避免冲突
├── L5: 性能优化指南 (Memo、Callback、懒加载、列表优化)
│ └── 目标: 应用流畅与用户体验
└── L6: 项目结构与架构 (目录组织、路由、配置、静态资源)
└── 目标: 项目可扩展与易于协作
```
---
## 二、L1 - 基础与核心规范
这是最基础也是必须遵守的规范,保证了代码的一致性和可读性。
### 1. 命名规范 (Naming Conventions)
#### 组件命名
使用 **PascalCase** (大驼峰命名法),且名称与文件名一致。
```tsx
// ✅ 正确
// UserProfile.tsx
function UserProfile() { ... }
// ❌ 错误
// userProfile.tsx
function user_profile() { ... }
function User_Profile() { ... }
```
#### 属性命名
使用 **camelCase** (小驼峰命名法)。
```tsx
// ✅ 正确
<Button onClick={handleClick} userName={userName} />
// ❌ 错误
<Button ONCLICK={handleClick} UserName={userName} />
```
#### 自定义事件处理函数
`handle` 开头,后接事件名或操作名。
```tsx
const handleInputChange = () => { ... };
const handleSubmit = () => { ... };
const handleDeleteUser = () => { ... };
```
#### 布尔型 Props
前缀使用 `is`, `has`, `should` 等,使其语义更明确。
```tsx
// ✅ 正确
<Button isDisabled={true} hasError={false} shouldShow={true} />
// ❌ 错误
<Button disabled={true} error={false} show={true} />
```
#### 常量命名
使用 **UPPER_SNAKE_CASE** (全大写下划线分隔)。
```tsx
const MAX_COUNT = 10;
const API_BASE_URL = "https://api.example.com";
const DEFAULT_TIMEOUT = 5000;
```
### 2. 文件组织 (File Organization)
#### 文件命名
- 组件文件:使用 PascalCase`UserProfile.tsx`
- 工具函数:使用 camelCase`formatDate.ts`
- 常量文件:使用 UPPER_SNAKE_CASE`API_CONSTANTS.ts`
- 样式文件:使用 kebab-case 或与组件同名,如 `user-profile.module.scss``UserProfile.module.scss`
#### 目录结构
```
src/
├── components/ # 通用组件
│ ├── Button/
│ │ ├── index.tsx
│ │ ├── Button.module.scss
│ │ └── types.ts
│ └── Modal/
├── pages/ # 页面组件
│ ├── Home/
│ └── Profile/
├── hooks/ # 自定义 Hooks
├── utils/ # 工具函数
├── store/ # 状态管理
├── api/ # API 接口
└── types/ # TypeScript 类型定义
```
### 3. JSX 编写规范
#### 基本规则
```tsx
// ✅ 正确:自闭合标签
<img src={avatar} alt="Avatar" />
<input type="text" value={value} />
// ❌ 错误
<img src={avatar} alt="Avatar"></img>
<input type="text" value={value}></input>
```
#### 条件渲染
```tsx
// ✅ 推荐:使用逻辑与运算符
{
isLoading && <LoadingSpinner />;
}
// ✅ 推荐:三元运算符(简单条件)
{
isLoggedIn ? <UserMenu /> : <LoginButton />;
}
// ✅ 推荐:提前返回(复杂条件)
if (!user) return <LoginPrompt />;
return <Dashboard />;
```
#### 列表渲染
```tsx
// ✅ 正确:使用 key
{
users.map(user => <UserItem key={user.id} user={user} />);
}
// ❌ 错误:使用索引作为 key除非列表是静态的
{
users.map((user, index) => <UserItem key={index} user={user} />);
}
```
#### 属性展开
```tsx
// ✅ 正确:使用展开运算符
const props = { name: "John", age: 30 };
<UserProfile {...props} />
// ❌ 错误:逐个传递
<UserProfile name={props.name} age={props.age} />
```
### 4. Props 类型检查
#### TypeScript 类型定义
```tsx
// ✅ 推荐:使用 TypeScript
interface UserProfileProps {
name: string;
age: number;
email?: string;
isActive: boolean;
onUpdate: (id: number) => void;
}
const UserProfile: React.FC<UserProfileProps> = ({
name,
age,
email,
isActive,
onUpdate,
}) => {
// ...
};
```
#### 默认值
```tsx
// ✅ 使用默认参数
const UserProfile: React.FC<UserProfileProps> = ({
name,
age,
email = "",
isActive = false,
onUpdate,
}) => {
// ...
};
// 或使用 defaultProps不推荐TypeScript 中已废弃)
```
---
## 三、L2 - 组件设计模式
### 1. 组件拆分与组合 (Component Splitting & Composition)
#### 单一职责原则
每个组件应该只做一件事。
```tsx
// ❌ 错误:组件职责过多
const UserDashboard = () => {
return (
<div>
<UserProfile />
<UserSettings />
<UserMessages />
<UserNotifications />
</div>
);
};
// ✅ 正确:拆分为多个小组件
const UserDashboard = () => {
return (
<div>
<UserProfile />
<UserSettings />
<UserMessages />
<UserNotifications />
</div>
);
};
```
#### 组件大小控制
- 单个组件文件不超过 300 行
- 如果超过,考虑拆分为多个子组件
- 复杂逻辑提取为自定义 Hook
```tsx
// ✅ 正确:使用自定义 Hook 提取逻辑
const useUserData = (userId: number) => {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetchUser(userId).then(data => {
setUser(data);
setLoading(false);
});
}, [userId]);
return { user, loading };
};
const UserProfile = ({ userId }: { userId: number }) => {
const { user, loading } = useUserData(userId);
// ...
};
```
### 2. 展示组件与容器组件 (Presentational vs Container Components)
#### 展示组件 (Presentational Components)
- 只负责 UI 渲染
- 通过 props 接收数据和回调
- 不依赖业务逻辑
```tsx
// ✅ 展示组件
interface ButtonProps {
label: string;
onClick: () => void;
disabled?: boolean;
}
const Button: React.FC<ButtonProps> = ({ label, onClick, disabled }) => {
return (
<button onClick={onClick} disabled={disabled}>
{label}
</button>
);
};
```
#### 容器组件 (Container Components)
- 负责数据获取和状态管理
- 包含业务逻辑
- 将数据传递给展示组件
```tsx
// ✅ 容器组件
const UserListContainer = () => {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetchUsers().then(data => {
setUsers(data);
setLoading(false);
});
}, []);
if (loading) return <LoadingSpinner />;
return <UserList users={users} />;
};
```
---
## 四、L3 - 状态管理规范
### 1. State 放置原则
#### 状态提升 (Lifting State Up)
将共享状态提升到最近的公共父组件。
```tsx
// ❌ 错误:状态分散
const ChildA = () => {
const [sharedValue, setSharedValue] = useState("");
// ...
};
const ChildB = () => {
const [sharedValue, setSharedValue] = useState("");
// ...
};
// ✅ 正确:状态提升
const Parent = () => {
const [sharedValue, setSharedValue] = useState("");
return (
<>
<ChildA value={sharedValue} onChange={setSharedValue} />
<ChildB value={sharedValue} onChange={setSharedValue} />
</>
);
};
```
#### 状态位置判断
- **组件内部状态**:只在该组件内使用
- **共享状态**:提升到公共父组件或使用全局状态管理
- **服务器状态**:使用 React Query 或 SWR
### 2. 使用 useReducer 管理复杂状态
当状态逻辑复杂时,使用 `useReducer` 替代多个 `useState`
```tsx
// ✅ 使用 useReducer
interface State {
count: number;
step: number;
}
type Action =
| { type: "increment" }
| { type: "decrement" }
| { type: "reset" }
| { type: "setStep"; step: number };
const reducer = (state: State, action: Action): State => {
switch (action.type) {
case "increment":
return { ...state, count: state.count + state.step };
case "decrement":
return { ...state, count: state.count - state.step };
case "reset":
return { ...state, count: 0 };
case "setStep":
return { ...state, step: action.step };
default:
return state;
}
};
const Counter = () => {
const [state, dispatch] = useReducer(reducer, { count: 0, step: 1 });
// ...
};
```
### 3. 全局状态管理
#### Zustand (本项目使用)
```tsx
// ✅ 使用 Zustand
import { create } from "zustand";
interface UserStore {
user: User | null;
setUser: (user: User) => void;
clearUser: () => void;
}
const useUserStore = create<UserStore>(set => ({
user: null,
setUser: user => set({ user }),
clearUser: () => set({ user: null }),
}));
// 使用
const UserProfile = () => {
const user = useUserStore(state => state.user);
const setUser = useUserStore(state => state.setUser);
// ...
};
```
#### Context API
适用于中等规模的全局状态。
```tsx
// ✅ 使用 Context
const UserContext = createContext<UserContextType | null>(null);
export const UserProvider: React.FC<{ children: React.ReactNode }> = ({
children,
}) => {
const [user, setUser] = useState<User | null>(null);
return (
<UserContext.Provider value={{ user, setUser }}>
{children}
</UserContext.Provider>
);
};
```
---
## 五、L4 - 样式与CSS策略
### 1. CSS Modules (推荐)
本项目使用 **CSS Modules** 配合 **SCSS**
```tsx
// ✅ 使用 CSS Modules
import styles from "./UserProfile.module.scss";
const UserProfile = () => {
return <div className={styles.container}>...</div>;
};
```
```scss
// UserProfile.module.scss
.container {
padding: 16px;
background-color: #fff;
.title {
font-size: 24px;
font-weight: bold;
}
}
```
#### 优势
- ✅ 样式作用域隔离,避免冲突
- ✅ 支持 TypeScript 类型检查
- ✅ 支持 SCSS 嵌套和变量
- ✅ 构建时优化,自动移除未使用的样式
### 2. 样式命名规范
```scss
// ✅ 推荐BEM 命名法
.user-profile {
&__header {
// ...
}
&__body {
// ...
}
&__footer {
// ...
}
&--active {
// ...
}
}
```
### 3. 样式变量
```scss
// ✅ 使用 SCSS 变量
$primary-color: #1890ff;
$secondary-color: #52c41a;
$font-size-base: 14px;
.button {
background-color: $primary-color;
font-size: $font-size-base;
}
```
---
## 六、L5 - 性能优化指南
### 1. 避免不必要的重新渲染
#### 使用 React.memo
```tsx
// ✅ 使用 React.memo 优化子组件
const UserItem = React.memo(
({ user }: { user: User }) => {
return <div>{user.name}</div>;
},
(prevProps, nextProps) => {
// 自定义比较函数
return prevProps.user.id === nextProps.user.id;
},
);
```
#### 使用 useMemo
```tsx
// ✅ 使用 useMemo 缓存计算结果
const ExpensiveComponent = ({ items }: { items: Item[] }) => {
const sortedItems = useMemo(() => {
return items.sort((a, b) => a.price - b.price);
}, [items]);
return <div>{/* 使用 sortedItems */}</div>;
};
```
#### 使用 useCallback
```tsx
// ✅ 使用 useCallback 缓存函数
const Parent = () => {
const [count, setCount] = useState(0);
const handleClick = useCallback(() => {
setCount(prev => prev + 1);
}, []);
return <Child onClick={handleClick} />;
};
```
### 2. 代码分割与懒加载 (Lazy Loading)
```tsx
// ✅ 使用 React.lazy 和 Suspense
import { lazy, Suspense } from "react";
const UserProfile = lazy(() => import("./pages/UserProfile"));
const App = () => {
return (
<Suspense fallback={<LoadingSpinner />}>
<UserProfile />
</Suspense>
);
};
```
### 3. 列表渲染优化
#### 虚拟列表
对于长列表,使用虚拟滚动。
```tsx
// ✅ 使用虚拟列表组件
import { FixedSizeList } from "react-window";
const VirtualizedList = ({ items }: { items: Item[] }) => {
return (
<FixedSizeList
height={600}
itemCount={items.length}
itemSize={50}
width="100%"
>
{({ index, style }) => (
<div style={style}>
<Item item={items[index]} />
</div>
)}
</FixedSizeList>
);
};
```
---
## 七、L6 - 项目结构与架构
### 1. 功能分区目录结构 (Feature-Based Structure)
本项目采用功能分区 + 类型分区的混合结构:
```
src/
├── components/ # 通用组件(可复用)
│ ├── Button/
│ ├── Modal/
│ └── ...
├── pages/ # 页面组件(路由级别)
│ ├── Home/
│ ├── Profile/
│ └── ...
├── hooks/ # 自定义 Hooks
│ ├── useAuth.ts
│ └── useLocalStorage.ts
├── utils/ # 工具函数
│ ├── formatDate.ts
│ └── validate.ts
├── store/ # 状态管理Zustand
│ ├── module/
│ │ ├── user.ts
│ │ └── weChat.ts
│ └── index.ts
├── api/ # API 接口
│ ├── request.ts
│ └── module/
│ └── wechat.ts
├── types/ # TypeScript 类型定义
│ ├── user.ts
│ └── weChat.ts
└── router/ # 路由配置
├── index.tsx
└── module/
```
### 2. 使用绝对路径导入
本项目已配置路径别名 `@` 指向 `src` 目录。
```tsx
// ✅ 使用绝对路径
import { Button } from "@/components/Button";
import { useUserStore } from "@/store/module/user";
import { formatDate } from "@/utils/formatDate";
// ❌ 避免相对路径
import { Button } from "../../../components/Button";
```
### 3. 组件导出规范
```tsx
// ✅ 推荐:使用 index.ts 统一导出
// components/Button/index.tsx
export { default } from "./Button";
export type { ButtonProps } from "./types";
// 使用
import Button from "@/components/Button";
import type { ButtonProps } from "@/components/Button";
```
### 4. 类型定义规范
```tsx
// ✅ 类型定义文件
// types/user.ts
export interface User {
id: number;
name: string;
email: string;
}
export type UserRole = "admin" | "user" | "guest";
// 使用
import type { User, UserRole } from "@/types/user";
```
---
## 📝 总结
### 核心原则
1. **一致性**:保持代码风格和命名规范的一致性
2. **可读性**:代码应该易于理解和维护
3. **可复用性**:组件和函数应该尽可能可复用
4. **性能**:关注性能优化,但不要过度优化
5. **类型安全**:充分利用 TypeScript 的类型检查
### 检查清单
在提交代码前,确保:
- [ ] 组件命名符合 PascalCase
- [ ] 函数命名符合 camelCase
- [ ] 使用了 TypeScript 类型定义
- [ ] 样式使用了 CSS Modules
- [ ] 避免了不必要的重新渲染
- [ ] 使用了绝对路径导入
- [ ] 代码通过了 ESLint 检查
- [ ] 代码通过了 Prettier 格式化
### 参考资源
- [React 官方文档](https://react.dev/)
- [TypeScript 官方文档](https://www.typescriptlang.org/)
- [Zustand 文档](https://zustand-demo.pmnd.rs/)
- [CSS Modules 文档](https://github.com/css-modules/css-modules)
---
**最后更新**: 2025-01-XX
**维护者**: 开发团队

View File

@@ -1,4 +1,5 @@
## 使用技术栈
- React 18
- TypeScript
- Vite新一代前端构建工具
@@ -12,15 +13,22 @@
- 路径别名 @ 指向 src 目录
## 关于兼容与工程化
- 自动化脚本yarn lint、yarn dev 等)
- 移动端 rem 适配html 根字体 + pxtorem
- iOS 浏览器滚动回弹兼容问题已通过全局样式处理
- 支持 VS Code 编辑器自动格式化(推荐配合 ESLint/Prettier 插件)
## 目录结构简要
- src/ 业务源码pages、api、styles、App.tsx、main.tsx 等)
- public/ 静态资源目录
- index.html 项目入口(根目录)
- vite.config.ts 构建与路径别名配置
- tsconfig.json TypeScript 配置
- .eslintrc.js 代码规范配置
- .eslintrc.js 代码规范配置
## 新增优化组件
TanStack Query
Sentry