一尘子、道法自然、博客园、前端

Vue3 + TypeScript 项目目录结构

📁 项目根目录

项目名称/
├── .vscode/                    # VSCode 配置
│   ├── settings.json          # 编辑器设置
│   └── extensions.json         # 推荐扩展
├── .husky/                     # Git hooks
│   └── pre-commit             # 提交前检查
├── public/                     # 静态资源(不经过打包)
│   ├── favicon.ico
│   └── index.html
├── src/                        # 源代码目录
│   ├── api/                    # API 接口管理
│   │   ├── modules/           # 按模块划分的接口
│   │   │   ├── user.ts
│   │   │   ├── order.ts
│   │   │   └── product.ts
│   │   ├── request.ts          # axios 封装
│   │   ├── types.ts            # API 类型定义
│   │   └── index.ts            # 统一导出
│   │
│   ├── assets/                 # 静态资源(经过打包)
│   │   ├── images/            # 图片资源
│   │   │   ├── common/        # 公共图片
│   │   │   └── icons/         # 图标
│   │   ├── fonts/             # 字体文件
│   │   └── styles/            # 全局样式
│   │       ├── variables.scss # SCSS 变量
│   │       ├── mixins.scss    # SCSS 混入
│   │       ├── reset.scss     # 样式重置
│   │       └── index.scss     # 样式入口
│   │
│   ├── components/             # 公共组件
│   │   ├── common/            # 通用基础组件
│   │   │   ├── Button/
│   │   │   │   ├── Button.vue
│   │   │   │   └── index.ts
│   │   │   ├── Input/
│   │   │   │   ├── Input.vue
│   │   │   │   └── index.ts
│   │   │   └── Table/
│   │   │       ├── Table.vue
│   │   │       └── index.ts
│   │   │
│   │   ├── business/          # 业务组件
│   │   │   ├── UserCard/      # 用户卡片组件
│   │   │   │   ├── UserCard.vue
│   │   │   │   ├── components/ # 子组件
│   │   │   │   │   ├── UserAvatar.vue
│   │   │   │   │   ├── UserInfo.vue
│   │   │   │   │   └── UserActions.vue
│   │   │   │   ├── composables/ # 组件相关 hooks(逻辑复杂时使用)
│   │   │   │   │   └── useUserCard.ts
│   │   │   │   ├── styles/    # 组件样式(样式过长时抽离)
│   │   │   │   │   └── index.scss
│   │   │   │   └── index.ts
│   │   │   │
│   │   │   ├── OrderList/     # 订单列表组件
│   │   │   │   ├── OrderList.vue
│   │   │   │   ├── components/
│   │   │   │   │   ├── OrderItem.vue
│   │   │   │   │   ├── OrderStatus.vue
│   │   │   │   │   └── OrderActions.vue
│   │   │   │   ├── composables/
│   │   │   │   │   └── useOrderList.ts
│   │   │   │   ├── styles/
│   │   │   │   │   └── index.scss
│   │   │   │   └── index.ts
│   │   │   │
│   │   │   └── ProductCard/   # 商品卡片组件
│   │   │       ├── ProductCard.vue
│   │   │       ├── components/
│   │   │       │   ├── ProductImage.vue
│   │   │       │   ├── ProductPrice.vue
│   │   │       │   └── ProductTags.vue
│   │   │       ├── composables/
│   │   │       │   └── useProductCard.ts
│   │   │       ├── styles/
│   │   │       │   └── index.scss
│   │   │       └── index.ts
│   │   │
│   │   └── layout/            # 布局组件
│   │       ├── Header/
│   │       │   ├── Header.vue
│   │       │   ├── components/
│   │       │   │   ├── NavMenu.vue
│   │       │   │   ├── UserDropdown.vue
│   │       │   │   └── SearchBar.vue
│   │       │   ├── composables/
│   │       │   │   └── useHeader.ts
│   │       │   ├── styles/
│   │       │   │   └── index.scss
│   │       │   └── index.ts
│   │       │
│   │       ├── Sidebar/
│   │       │   ├── Sidebar.vue
│   │       │   ├── components/
│   │       │   │   └── MenuItem.vue
│   │       │   ├── composables/
│   │       │   │   └── useSidebar.ts
│   │       │   ├── styles/
│   │       │   │   └── index.scss
│   │       │   └── index.ts
│   │       │
│   │       └── Footer/
│   │           ├── Footer.vue
│   │           ├── styles/
│   │           │   └── index.scss
│   │           └── index.ts
│   │
│   ├── composables/            # 组合式函数(Hooks)
│   │   ├── useAuth.ts          # 认证相关
│   │   ├── useTable.ts         # 表格相关
│   │   ├── useForm.ts          # 表单相关
│   │   ├── usePagination.ts   # 分页相关
│   │   ├── useRequest.ts       # 请求相关
│   │   ├── usePermission.ts   # 权限相关
│   │   ├── useDebounce.ts     # 防抖
│   │   ├── useThrottle.ts     # 节流
│   │   ├── useLocalStorage.ts # 本地存储
│   │   └── index.ts            # 统一导出
│   │
│   ├── directives/             # 自定义指令
│   │   ├── v-loading.ts
│   │   ├── v-permission.ts
│   │   └── index.ts
│   │
│   ├── plugins/                # 插件配置
│   │   ├── element-plus.ts    # Element Plus 配置
│   │   ├── pinia.ts            # Pinia 配置
│   │   └── index.ts
│   │
│   ├── router/                 # 路由配置
│   │   ├── modules/            # 路由模块
│   │   │   ├── user.ts
│   │   │   ├── order.ts
│   │   │   └── product.ts
│   │   ├── index.ts            # 路由入口
│   │   ├── guards.ts           # 路由守卫
│   │   └── types.ts            # 路由类型
│   │
│   ├── stores/                 # Pinia 状态管理
│   │   ├── modules/            # 状态模块
│   │   │   ├── user.ts         # 用户状态
│   │   │   ├── app.ts          # 应用状态
│   │   │   ├── permission.ts   # 权限状态
│   │   │   └── order.ts        # 订单状态
│   │   └── index.ts            # Store 入口
│   │
│   ├── views/                  # 页面级组件(业务页面)
│   │   ├── login/              # 登录页面
│   │   │   ├── Login.vue
│   │   │   ├── components/     # 页面级子组件
│   │   │   │   ├── LoginForm.vue
│   │   │   │   └── LoginHeader.vue
│   │   │   ├── composables/    # 页面级 hooks(逻辑复杂时使用)
│   │   │   │   └── useLogin.ts
│   │   │   ├── styles/         # 页面样式(样式过长时抽离)
│   │   │   │   └── index.scss
│   │   │   └── index.ts
│   │   │
│   │   ├── dashboard/          # 仪表盘页面
│   │   │   ├── Dashboard.vue
│   │   │   ├── components/
│   │   │   │   ├── StatCard.vue
│   │   │   │   ├── ChartCard.vue
│   │   │   │   └── RecentActivity.vue
│   │   │   ├── composables/
│   │   │   │   └── useDashboard.ts
│   │   │   ├── styles/
│   │   │   │   └── index.scss
│   │   │   └── index.ts
│   │   │
│   │   ├── user/               # 用户管理页面
│   │   │   ├── index.vue       # 用户列表
│   │   │   ├── components/
│   │   │   │   ├── UserTable.vue
│   │   │   │   ├── UserSearch.vue
│   │   │   │   └── UserDialog.vue
│   │   │   ├── composables/
│   │   │   │   └── useUserManagement.ts
│   │   │   ├── styles/
│   │   │   │   └── index.scss
│   │   │   │
│   │   │   ├── detail/         # 用户详情子页面
│   │   │   │   ├── UserDetail.vue
│   │   │   │   ├── components/
│   │   │   │   │   ├── UserInfo.vue
│   │   │   │   │   └── UserHistory.vue
│   │   │   │   ├── composables/
│   │   │   │   │   └── useUserDetail.ts
│   │   │   │   └── styles/
│   │   │   │       └── index.scss
│   │   │   │
│   │   │   └── edit/           # 用户编辑子页面
│   │   │       ├── UserEdit.vue
│   │   │       ├── components/
│   │   │       │   └── UserForm.vue
│   │   │       ├── composables/
│   │   │       │   └── useUserEdit.ts
│   │   │       └── styles/
│   │   │           └── index.scss
│   │   │
│   │   ├── order/              # 订单管理页面
│   │   │   ├── index.vue       # 订单列表
│   │   │   ├── components/
│   │   │   │   ├── OrderTable.vue
│   │   │   │   ├── OrderFilter.vue
│   │   │   │   └── OrderDetailDialog.vue
│   │   │   ├── composables/
│   │   │   │   └── useOrderManagement.ts
│   │   │   ├── styles/
│   │   │   │   └── index.scss
│   │   │   │
│   │   │   └── detail/         # 订单详情子页面
│   │   │       ├── OrderDetail.vue
│   │   │       ├── components/
│   │   │       │   ├── OrderInfo.vue
│   │   │       │   ├── OrderItems.vue
│   │   │       │   └── OrderTimeline.vue
│   │   │       ├── composables/
│   │   │       │   └── useOrderDetail.ts
│   │   │       └── styles/
│   │   │           └── index.scss
│   │   │
│   │   └── product/            # 商品管理页面
│   │       ├── index.vue       # 商品列表
│   │       ├── components/
│   │       │   ├── ProductTable.vue
│   │       │   ├── ProductSearch.vue
│   │       │   └── ProductDialog.vue
│   │       ├── composables/
│   │       │   └── useProductManagement.ts
│   │       ├── styles/
│   │       │   └── index.scss
│   │       │
│   │       └── detail/         # 商品详情子页面
│   │           ├── ProductDetail.vue
│   │           ├── components/
│   │           │   ├── ProductInfo.vue
│   │           │   ├── ProductGallery.vue
│   │           │   └── ProductSpecs.vue
│   │           ├── composables/
│   │           │   └── useProductDetail.ts
│   │           └── styles/
│   │               └── index.scss
│   │
│   ├── utils/                  # 工具函数
│   │   ├── format.ts           # 格式化工具
│   │   ├── validate.ts         # 验证工具
│   │   ├── date.ts             # 日期工具
│   │   ├── storage.ts          # 存储工具
│   │   ├── common.ts           # 通用工具
│   │   └── index.ts
│   │
│   ├── types/                  # TypeScript 类型定义
│   │   ├── api.ts              # API 类型
│   │   ├── user.ts             # 用户类型
│   │   ├── order.ts            # 订单类型
│   │   ├── product.ts          # 商品类型
│   │   ├── common.ts           # 通用类型
│   │   └── index.ts
│   │
│   ├── constants/              # 常量定义
│   │   ├── api.ts              # API 常量
│   │   ├── status.ts           # 状态常量
│   │   └── index.ts
│   │
│   ├── config/                 # 配置文件
│   │   ├── index.ts            # 配置入口
│   │   └── env.ts              # 环境配置
│   │
│   ├── enums/                  # 枚举定义
│   │   ├── status.ts           # 状态枚举
│   │   ├── user.ts             # 用户相关枚举
│   │   └── index.ts
│   │
│   ├── App.vue                 # 根组件
│   ├── main.ts                 # 应用入口
│   └── env.d.ts                # 环境类型声明
│
├── tests/                      # 测试文件
│   ├── unit/                   # 单元测试
│   │   ├── components/
│   │   ├── composables/
│   │   └── utils/
│   ├── e2e/                    # 端到端测试
│   ├── setup.ts                # 测试配置
│   └── utils/                  # 测试工具
│
├── .eslintrc.cjs               # ESLint 配置
├── .prettierrc                 # Prettier 配置
├── .prettierignore             # Prettier 忽略文件
├── .gitignore                  # Git 忽略文件
├── .env                        # 环境变量
├── .env.development            # 开发环境变量
├── .env.production             # 生产环境变量
├── index.html                  # HTML 模板
├── package.json                # 项目依赖
├── pnpm-lock.yaml              # 依赖锁定文件(或 yarn.lock)
├── tsconfig.json               # TypeScript 配置
├── tsconfig.node.json          # Node TypeScript 配置
├── vite.config.ts              # Vite 配置
└── README.md                   # 项目说明

📋 目录说明

1. 复杂组件结构(components/business/)

复杂业务组件采用模块化组织,每个组件包含:

  • 主组件文件ComponentName.vue - 使用 <script setup lang="ts">
  • 子组件目录components/ - 存放组件内部使用的子组件
  • 组合式函数composables/ - 逻辑复杂时抽离业务逻辑 hooks
  • 样式文件styles/index.scss - 样式过长时抽离为单独文件
  • 导出文件index.ts - 统一导出

逻辑处理方案:

  • 简单逻辑:直接在 <script setup> 中编写
  • 复杂逻辑:抽离到 composables/useComponentName.ts

样式处理方案:

  • 简单样式:使用 <style scoped> 在组件内
  • 复杂样式:抽离到 styles/index.scss

示例:UserCard 组件结构

UserCard/
├── UserCard.vue              # 主组件(<script setup lang="ts">)
├── components/               # 子组件
│   ├── UserAvatar.vue       # 用户头像
│   ├── UserInfo.vue         # 用户信息
│   └── UserActions.vue      # 用户操作按钮
├── composables/             # 组件 hooks(逻辑复杂时使用)
│   └── useUserCard.ts       # 用户卡片相关逻辑
├── styles/                  # 组件样式(样式过长时抽离)
│   └── index.scss           # 样式文件
└── index.ts                 # 导出

2. 业务组件结构(views/)

页面级组件采用相同的模块化结构:

  • 主页面文件PageName.vueindex.vue - 使用 <script setup lang="ts">
  • 子组件目录components/ - 页面内部使用的组件
  • 组合式函数composables/ - 逻辑复杂时抽离页面级业务逻辑
  • 样式文件styles/index.scss - 样式过长时抽离为单独文件
  • 子页面目录:支持嵌套的子页面(如 detail/edit/

逻辑处理方案:

  • 简单逻辑:直接在 <script setup> 中编写
  • 复杂逻辑:抽离到 composables/usePageName.ts

样式处理方案:

  • 简单样式:使用 <style scoped> 在组件内
  • 复杂样式:抽离到 styles/index.scss

示例:用户管理页面结构

user/
├── index.vue                # 用户列表主页面
├── components/              # 页面级组件
│   ├── UserTable.vue       # 用户表格
│   ├── UserSearch.vue      # 搜索组件
│   └── UserDialog.vue      # 对话框组件
├── composables/            # 页面 hooks
│   └── useUserManagement.ts
├── styles/                 # 页面样式
│   └── index.scss
│
├── detail/                 # 用户详情子页面
│   ├── UserDetail.vue
│   ├── components/
│   ├── composables/
│   └── styles/
│
└── edit/                   # 用户编辑子页面
    ├── UserEdit.vue
    ├── components/
    ├── composables/
    └── styles/

3. 组合式函数(composables/)

全局可复用的业务逻辑 hooks:

  • 通用 hooksuseAuth.tsuseTable.tsuseForm.ts
  • 工具类 hooksuseDebounce.tsuseThrottle.tsuseLocalStorage.ts
  • 组件级 hooks:放在对应组件的 composables/ 目录下

示例:useTable.ts

// composables/useTable.ts
export function useTable<T = any>(api: Function) {
  const loading = ref(false)
  const tableData = ref<T[]>([])
  const pagination = reactive({
    current: 1,
    pageSize: 10,
    total: 0
  })
  
  // ... 表格相关逻辑
  
  return {
    loading,
    tableData,
    pagination,
    // ... 其他方法
  }
}

4. 样式抽离(styles/)

样式采用分层管理,遵循"样式过长时抽离"的原则:

  • 全局样式src/assets/styles/ - 变量、混入、重置样式
  • 组件样式components/*/styles/ - 组件样式过长时抽离
  • 页面样式views/*/styles/ - 页面样式过长时抽离

样式组织原则:

  1. 简单样式:使用 <style scoped lang="scss"> 在组件/页面内
  2. 复杂样式:当样式代码超过 100-150 行时,抽离到独立的 styles/index.scss 文件
  3. 全局样式:统一在 assets/styles/ 管理

样式文件结构:

assets/styles/
├── variables.scss    # SCSS 变量(颜色、尺寸等)
├── mixins.scss      # SCSS 混入(复用样式片段)
├── reset.scss       # 样式重置
└── index.scss       # 样式入口(导入所有全局样式)

components/UserCard/styles/
└── index.scss       # UserCard 组件样式(样式过长时抽离)

views/user/styles/
└── index.scss       # 用户管理页面样式(样式过长时抽离)

🔧 技术栈说明

  • Vue 3:使用 Composition API
  • TypeScript:类型安全
  • Pinia:状态管理
  • Element Plus:UI 组件库
  • Vite:构建工具
  • ESLint:代码检查
  • Prettier:代码格式化

📝 命名规范

  1. 组件命名:PascalCase(如 UserCard.vue
  2. 文件命名
    • Vue 组件:PascalCase
    • TypeScript 文件:camelCase
    • 工具函数:camelCase
  3. 目录命名:kebabCase(如 userManagement/
  4. 变量命名:camelCase
  5. 常量命名:UPPER_SNAKE_CASE

🎯 最佳实践

  1. 组件拆分:复杂组件拆分为多个子组件
  2. 逻辑抽离:业务逻辑抽离到 composables
  3. 样式隔离:每个组件/页面有独立的样式文件
  4. 类型定义:所有接口和数据结构都有类型定义
  5. 统一导出:使用 index.ts 统一导出,方便引用

✅ 符合业内规范的部分

1. 核心目录结构

  • src/ 作为源代码根目录
  • components/views/ 分离(组件库 vs 页面)
  • composables/ 用于组合式函数(Vue3 标准做法)
  • stores/ 使用 modules/ 模块化组织(Pinia 推荐)
  • router/ 使用 modules/ 模块化组织
  • api/ 使用 modules/ 按业务模块划分
  • types/ 独立目录管理类型定义
  • utils/ 工具函数集中管理

2. 组件组织方式

  • components/common/ 通用基础组件
  • components/business/ 业务组件
  • components/layout/ 布局组件
  • ✅ 组件内部包含子组件、composables、样式(模块化组织)

3. 页面组织方式

  • views/ 按业务模块组织
  • ✅ 支持嵌套子页面(detail、edit 等)
  • ✅ 页面级组件、hooks、样式分离

4. 样式管理

  • ✅ 全局样式在 assets/styles/
  • ✅ 组件样式独立管理
  • ✅ 使用 SCSS 变量和混入

5. 配置文件

  • ✅ ESLint、Prettier 配置
  • ✅ TypeScript 配置
  • ✅ 环境变量文件
posted @ 2025-12-04 16:03  一尘子!  阅读(0)  评论(0)    收藏  举报
Live2D
返回顶端