项目结构 #

一、项目结构概述 #

1.1 为什么需要良好的项目结构 #

优势 说明
可维护性 代码易于查找和修改
可扩展性 新功能易于添加
可读性 团队成员易于理解
复用性 组件和逻辑易于复用

1.2 基本原则 #

  • 按功能模块组织
  • 相关文件放在一起
  • 保持结构扁平
  • 命名清晰一致

二、常见项目结构 #

2.1 按类型组织 #

text
src/
├── components/          # 组件
│   ├── common/         # 通用组件
│   ├── layout/         # 布局组件
│   └── ui/             # UI组件
├── hooks/              # 自定义Hooks
├── pages/              # 页面组件
├── services/           # API服务
├── store/              # 状态管理
├── utils/              # 工具函数
├── constants/          # 常量
├── styles/             # 全局样式
└── App.jsx

2.2 按功能模块组织(推荐) #

text
src/
├── features/           # 功能模块
│   ├── auth/
│   │   ├── components/
│   │   ├── hooks/
│   │   ├── services/
│   │   ├── store/
│   │   └── index.js
│   ├── todos/
│   │   ├── components/
│   │   ├── hooks/
│   │   ├── store/
│   │   └── index.js
│   └── users/
├── components/         # 共享组件
│   ├── Button/
│   ├── Input/
│   └── Modal/
├── hooks/              # 共享Hooks
├── layouts/            # 布局组件
├── pages/              # 页面入口
├── services/           # API服务
├── store/              # 全局状态
├── utils/              # 工具函数
└── App.jsx

2.3 小型项目结构 #

text
src/
├── components/
│   ├── Header.jsx
│   ├── Footer.jsx
│   └── TodoList.jsx
├── hooks/
│   └── useTodos.js
├── App.jsx
└── main.jsx

三、组件组织 #

3.1 组件文件夹结构 #

text
components/
├── Button/
│   ├── Button.jsx       # 组件实现
│   ├── Button.test.jsx  # 测试文件
│   ├── Button.module.css # 样式文件
│   ├── Button.stories.jsx # Storybook
│   └── index.js         # 导出文件

3.2 组件文件模板 #

javascript
// Button.jsx
import styles from './Button.module.css';

export function Button({ children, variant = 'primary', onClick }) {
  return (
    <button
      className={`${styles.button} ${styles[variant]}`}
      onClick={onClick}
    >
      {children}
    </button>
  );
}

// index.js
export { Button } from './Button';
export { default } from './Button';

3.3 组件分类 #

text
components/
├── ui/                  # 基础UI组件
│   ├── Button/
│   ├── Input/
│   ├── Select/
│   └── Modal/
├── layout/              # 布局组件
│   ├── Header/
│   ├── Footer/
│   ├── Sidebar/
│   └── Layout/
└── common/              # 通用业务组件
    ├── UserCard/
    ├── ProductCard/
    └── SearchBar/

四、状态管理组织 #

4.1 Context组织 #

text
contexts/
├── AuthContext.jsx
├── ThemeContext.jsx
├── CartContext.jsx
└── index.js

4.2 Redux组织 #

text
store/
├── index.js
├── rootReducer.js
└── middleware/

features/
├── auth/
│   ├── authSlice.js
│   ├── authSelectors.js
│   └── authThunks.js
└── todos/
    ├── todosSlice.js
    ├── todosSelectors.js
    └── todosThunks.js

五、路由组织 #

5.1 路由配置 #

text
routes/
├── index.jsx            # 路由入口
├── publicRoutes.jsx     # 公开路由
├── protectedRoutes.jsx  # 受保护路由
└── constants.js         # 路由常量

5.2 路由示例 #

javascript
// routes/index.jsx
import { createBrowserRouter } from 'react-router-dom';
import { publicRoutes } from './publicRoutes';
import { protectedRoutes } from './protectedRoutes';

export const router = createBrowserRouter([
  ...publicRoutes,
  ...protectedRoutes
]);

// routes/publicRoutes.jsx
export const publicRoutes = [
  {
    path: '/',
    element: <Home />
  },
  {
    path: '/login',
    element: <Login />
  }
];

// routes/protectedRoutes.jsx
export const protectedRoutes = [
  {
    path: '/dashboard',
    element: (
      <ProtectedRoute>
        <Dashboard />
      </ProtectedRoute>
    )
  }
];

六、API服务组织 #

6.1 服务层结构 #

text
services/
├── api/
│   ├── client.js        # Axios实例
│   ├── interceptors.js  # 拦截器
│   └── endpoints.js     # 端点配置
├── auth/
│   └── authService.js
├── user/
│   └── userService.js
└── index.js

6.2 服务示例 #

javascript
// services/api/client.js
import axios from 'axios';

export const apiClient = axios.create({
  baseURL: import.meta.env.VITE_API_URL,
  timeout: 10000,
  headers: {
    'Content-Type': 'application/json'
  }
});

// services/auth/authService.js
import { apiClient } from '../api/client';

export const authService = {
  login: (credentials) => 
    apiClient.post('/auth/login', credentials),
  
  logout: () => 
    apiClient.post('/auth/logout'),
  
  refreshToken: (token) => 
    apiClient.post('/auth/refresh', { token }),
  
  getCurrentUser: () => 
    apiClient.get('/auth/me')
};

七、工具函数组织 #

7.1 工具目录 #

text
utils/
├── format/
│   ├── date.js
│   ├── number.js
│   └── string.js
├── validation/
│   ├── form.js
│   └── schema.js
├── storage/
│   ├── localStorage.js
│   └── sessionStorage.js
└── helpers/
    ├── array.js
    └── object.js

7.2 工具示例 #

javascript
// utils/format/date.js
export const formatDate = (date, format = 'YYYY-MM-DD') => {
  // 格式化日期
};

export const formatTime = (date) => {
  // 格式化时间
};

// utils/validation/form.js
export const isEmail = (value) => {
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
};

export const isPhone = (value) => {
  return /^1[3-9]\d{9}$/.test(value);
};

八、样式组织 #

8.1 样式目录 #

text
styles/
├── variables.css        # CSS变量
├── reset.css           # 重置样式
├── global.css          # 全局样式
├── utilities.css       # 工具类
└── themes/
    ├── light.css
    └── dark.css

8.2 CSS模块 #

css
/* components/Button/Button.module.css */
.button {
  padding: 0.5rem 1rem;
  border-radius: 4px;
  cursor: pointer;
}

.primary {
  background-color: var(--color-primary);
  color: white;
}

.secondary {
  background-color: var(--color-secondary);
  color: white;
}

九、配置文件 #

9.1 环境变量 #

bash
# .env.development
VITE_API_URL=http://localhost:3000/api
VITE_APP_TITLE=React App (Dev)

# .env.production
VITE_API_URL=https://api.example.com
VITE_APP_TITLE=React App

9.2 项目配置 #

javascript
// config/index.js
export const config = {
  api: {
    baseURL: import.meta.env.VITE_API_URL,
    timeout: 10000
  },
  app: {
    title: import.meta.env.VITE_APP_TITLE
  },
  features: {
    darkMode: true,
    i18n: true
  }
};

十、最佳实践 #

10.1 命名规范 #

类型 规范 示例
组件 PascalCase UserCard.jsx
Hook camelCase + use前缀 useAuth.js
工具函数 camelCase formatDate.js
常量 UPPER_SNAKE_CASE API_ENDPOINTS
CSS模块 camelCase button.module.css

10.2 导出规范 #

javascript
// 命名导出
export { Button };
export { useAuth };

// 默认导出(页面组件)
export default HomePage;

// 统一导出
export { Button } from './Button';
export { IconButton } from './IconButton';

10.3 导入顺序 #

javascript
// 1. React相关
import { useState, useEffect } from 'react';

// 2. 第三方库
import { BrowserRouter } from 'react-router-dom';
import { useSelector } from 'react-redux';

// 3. 内部模块(按层级)
import { Button } from '@/components/Button';
import { useAuth } from '@/hooks/useAuth';
import { formatDate } from '@/utils/format';

// 4. 样式
import styles from './App.module.css';

十一、总结 #

要点 说明
按功能组织 相关文件放在一起
组件分类 UI组件、布局组件、业务组件
服务层 统一API调用
命名规范 保持一致性

核心原则:

  • 保持结构清晰
  • 相关文件就近放置
  • 遵循命名规范
  • 合理拆分模块
最后更新:2026-03-26