Skip to content

项目结构

本文档介绍 vue3-element-admin 的目录结构设计理念和组织方式。

架构选型

Vue 3 项目常见的架构模式有:

架构适用场景优点缺点
扁平结构小型项目、PoC简单直接不可扩展
原子设计组件库组件复用性高层级复杂
模块化中大型应用松耦合、可维护可能重复
Feature-Sliced大型长期项目高内聚、边界清晰初期复杂
微前端多团队协作独立部署协调成本高

本项目采用模块化架构,这是 Vue 3 应用最适合的架构方式:

  • 按功能模块划分目录
  • 模块间松耦合
  • 便于独立开发和维护
  • 可平滑演进到微前端

参考:Vue FAQ - Project Structure

目录结构

vue3-element-admin/
├── mock/                       # Mock 数据
├── public/                     # 静态资源(不经过构建)
│   └── favicon.ico
├── src/
│   ├── api/                    # API 接口层
│   │   ├── system/            # 系统管理模块
│   │   │   ├── user.ts
│   │   │   ├── role.ts
│   │   │   └── menu.ts
│   │   ├── auth.ts            # 认证接口
│   │   └── file.ts            # 文件接口
│   │
│   ├── assets/                 # 静态资源(经过构建)
│   │   ├── icons/             # SVG 图标
│   │   └── images/            # 图片资源
│   │
│   ├── components/             # 公共组件
│   │   ├── AiAssistant/       # AI 助手
│   │   ├── Breadcrumb/        # 面包屑
│   │   ├── CommandPalette/    # 命令面板
│   │   ├── CopyButton/        # 复制按钮
│   │   ├── CURD/              # CURD 快速开发组件
│   │   ├── DictSelect/        # 字典选择器
│   │   ├── DictTag/           # 字典标签
│   │   ├── ECharts/           # 图表组件
│   │   ├── Fullscreen/        # 全屏切换
│   │   ├── Hamburger/         # 菜单折叠
│   │   ├── IconSelect/        # 图标选择器
│   │   ├── InputTag/          # 标签输入
│   │   ├── LangSelect/        # 语言选择
│   │   ├── NoticeDropdown/    # 通知下拉
│   │   ├── OperationColumn/   # 操作列
│   │   ├── Pagination/        # 分页组件
│   │   ├── SizeSelect/        # 尺寸选择
│   │   ├── TableSelect/       # 表格选择器
│   │   ├── TenantSwitcher/    # 租户切换
│   │   ├── TextScroll/        # 文字滚动
│   │   ├── ThemeSwitch/       # 主题切换
│   │   ├── Upload/            # 上传组件
│   │   └── WangEditor/        # 富文本编辑器
│   │
│   ├── composables/            # 组合式函数
│   │   ├── ai/                # AI 相关
│   │   │   └── useAiAction.ts
│   │   ├── table/             # 表格相关
│   │   │   └── useTableSelection.ts
│   │   ├── websocket/         # 实时通信相关(WebSocket)
│   │   │   ├── useStomp.ts
│   │   │   ├── useDictSync.ts
│   │   │   └── useOnlineCount.ts
│   │   └── index.ts           # 统一导出
│   │
│   ├── constants/              # 常量定义
│   │   └── index.ts
│   │
│   ├── directives/             # 自定义指令
│   │   └── permission/        # 权限指令
│   │
│   ├── enums/                  # 枚举定义
│   │   ├── api.ts             # API 相关枚举
│   │   └── settings.ts        # 设置相关枚举
│   │
│   ├── lang/                   # 国际化
│   │   ├── package/           # 语言包
│   │   │   ├── zh-cn.json     # 中文
│   │   │   └── en.json        # 英文
│   │   ├── index.ts           # 入口配置
│   │   └── utils.ts           # 工具函数
│   │
│   ├── layouts/                # 布局组件
│   │   ├── components/        # 布局子组件
│   │   ├── index.vue          # 主布局
│   │   └── useLayout.ts       # 布局逻辑
│   │
│   ├── plugins/                # 插件配置
│   │   └── vxe-table.ts       # VXE Table 配置
│   │
│   ├── router/                 # 路由配置
│   │   ├── guards/            # 路由守卫
│   │   └── index.ts           # 路由实例
│   │
│   ├── store/                  # 状态管理
│   │   ├── modules/           # Store 模块
│   │   │   ├── user.ts
│   │   │   ├── app.ts
│   │   │   └── permission.ts
│   │   └── index.ts           # Store 入口
│   │
│   ├── styles/                 # 全局样式
│   │   ├── variables.scss     # 变量定义
│   │   └── index.scss         # 入口文件
│   │
│   ├── types/                  # 类型定义
│   │   ├── api/               # API 类型
│   │   └── global.d.ts        # 全局声明
│   │
│   ├── utils/                  # 工具函数
│   │   ├── request.ts         # HTTP 请求
│   │   ├── auth.ts            # 认证工具
│   │   └── storage.ts         # 存储工具
│   │
│   ├── views/                  # 页面组件
│   │   ├── dashboard/         # 仪表盘
│   │   ├── demo/              # 功能演示
│   │   ├── system/            # 系统管理
│   │   │   ├── user/         # 用户管理
│   │   │   ├── role/         # 角色管理
│   │   │   └── menu/         # 菜单管理
│   │   └── login/             # 登录页
│   │
│   ├── App.vue                 # 根组件
│   ├── main.ts                 # 入口文件
│   └── settings.ts             # 应用配置

├── tests/                      # 测试文件
│   └── setup.ts               # 测试配置
├── types/                      # 全局类型声明

├── .env.development            # 开发环境变量
├── .env.production             # 生产环境变量
├── index.html                  # HTML 模板
├── package.json
├── tsconfig.json
├── uno.config.ts               # UnoCSS 配置
├── vite.config.ts              # Vite 配置
└── vitest.config.ts            # Vitest 配置

目录说明

api - 接口层

按业务模块组织 API 接口,单文件模块直接放在 api 根目录。

api/
├── system/           # 多文件模块用目录
│   ├── user.ts
│   └── role.ts
├── auth.ts           # 单文件模块直接放根目录
└── file.ts

assets - 静态资源

存放需要经过构建处理的静态资源。

assets/
├── icons/            # SVG 图标(通过 UnoCSS Icons 加载)
└── images/           # 图片资源(会被压缩优化)

components - 公共组件

存放跨页面复用的公共组件,项目已重构为以下组件:

components/
├── AiAssistant/       # AI 助手组件
├── Breadcrumb/        # 面包屑导航
├── CommandPalette/    # 命令面板(快捷搜索)
├── CopyButton/        # 复制按钮
├── CURD/              # CURD 快速开发组件
│   ├── PageSearch.vue
│   ├── PageContent.vue
│   ├── PageModal.vue
│   ├── types.ts
│   └── usePage.ts
├── DictSelect/        # 字典选择器
├── DictTag/           # 字典标签
├── ECharts/           # 图表组件
├── Fullscreen/        # 全屏切换
├── Hamburger/         # 菜单折叠按钮
├── IconSelect/        # 图标选择器
├── InputTag/          # 标签输入
├── LangSelect/        # 语言选择
├── NoticeDropdown/    # 通知下拉
├── OperationColumn/   # 操作列
├── Pagination/        # 分页组件
├── SizeSelect/        # 尺寸选择
├── TableSelect/       # 表格选择器
├── TenantSwitcher/    # 租户切换
├── TextScroll/        # 文字滚动
├── ThemeSwitch/       # 主题切换
├── Upload/            # 上传组件
│   ├── FileUpload.vue
│   ├── MultiImageUpload.vue
│   └── SingleImageUpload.vue
└── WangEditor/        # 富文本编辑器

命名规范:PascalCase,多词命名

composables - 组合式函数

存放可复用的组合式函数(Composition API)。

composables/
├── ai/
│   └── useAiAction.ts      # AI 操作助手
├── table/
│   └── useTableSelection.ts # 表格选择管理
├── websocket/
│   ├── useStomp.ts         # STOMP 协议
│   ├── useDictSync.ts      # 字典同步
│   └── useOnlineCount.ts   # 在线人数
└── index.ts                # 统一导出

命名规范use 前缀 + camelCase

lang - 国际化

存放多语言配置和语言包。

lang/
├── package/
│   ├── zh-cn.json    # 中文语言包
│   └── en.json       # 英文语言包
├── index.ts          # i18n 配置入口
└── utils.ts          # 工具函数

layouts - 布局组件

存放页面布局相关组件。

layouts/
├── components/       # 布局子组件
├── index.vue         # 主布局入口
└── useLayout.ts      # 布局逻辑

store - 状态管理

使用 Pinia 进行状态管理,按功能模块拆分。

store/
├── modules/
│   ├── user.ts       # 用户状态
│   ├── app.ts        # 应用状态
│   ├── permission.ts # 权限状态
│   └── settings.ts   # 设置状态
└── index.ts          # 统一导出

views - 页面组件

按路由/功能模块组织页面组件。

views/
├── dashboard/
│   └── index.vue
├── demo/             # 功能演示页面
│   ├── curd/
│   ├── dictionary.vue
│   ├── icons.vue
│   └── ...
├── system/
│   ├── user/
│   │   ├── index.vue
│   │   └── components/
│   └── role/
│       └── index.vue
└── login/
    └── index.vue

设计原则

1. 单一职责

每个目录只负责一类功能:

  • api/ - 只放 API 接口
  • utils/ - 只放工具函数
  • components/ - 只放公共组件

2. 就近原则

页面私有组件放在页面目录下:

views/system/user/
├── index.vue
└── components/       # 只有 user 页面使用的组件
    └── UserForm.vue

3. 扁平优先

避免过深的目录嵌套,单文件模块不建目录:

# ✅ 好
api/auth.ts

# ❌ 不好
api/auth/index.ts     # 只有一个文件,不需要目录

4. 统一导出

每个模块目录提供 index.ts 统一导出:

typescript
// composables/index.ts
export * from "./table/useTableSelection";
export * from "./websocket";

使用时:

typescript
import { useTableSelection, useDictSync } from "@/composables";

模块依赖关系

views (页面)

components (组件) + composables (组合函数)

store (状态) + api (接口)

utils (工具) + types (类型) + constants (常量)

原则:上层可以依赖下层,下层不能依赖上层。

参考资料

基于 MIT 许可发布