Vue3 + Vite + TS 项目目录结构规范
谢藏锋
适用场景:统一适配小型官网/H5、中大型后台管理系统,区分简易版/完整版两套目录,规范组件存放、命名、分层逻辑,解决目录混乱、复用混乱、业务与UI混杂问题
核心设计思想:分层解耦、权责单一、复用隔离、业务与基础能力分离
一、项目目录整体区分规则
1. views:路由页面,可单独访问,承载完整业务页面
2. components:UI碎片,不可单独路由访问,只做视图展示
3. composables:纯逻辑碎片,无DOM结构,复用组合式逻辑
4. utils:通用工具函数,无业务、无Vue依赖
5. api:接口请求层,统一管理后端交互
6. stores:全局状态管理,跨页面数据缓存
二、完整目录
project-root/
├── public/ # 不打包静态资源
├── src/ # 项目核心源码
│ ├── api/ # 接口请求层
│ ├── assets/ # 可打包静态资源(图片/字体/全局样式)
│ ├── components/ # 全局公共组件(核心重点)
│ ├── composables/ # Vue3 通用hooks逻辑
│ ├── directives/ # 全局自定义指令
│ ├── layouts/ # 全局页面布局外壳
│ ├── plugins/ # 第三方插件注册
│ ├── router/ # 路由配置
│ ├── stores/ # Pinia状态管理
│ ├── types/ # TS全局类型定义
│ ├── utils/ # 通用工具函数
│ ├── views/ # 业务页面视图
│ ├── App.vue # 根组件
│ └── main.ts # 项目入口文件
├── .env.* # 环境变量配置
├── vite.config.ts # 构建配置
├── package.json
└── tsconfig.json三、各目录详细释义 & 落地规范
1. public 目录(静态资源)
存放内容:不经过Vite打包、压缩的原生静态文件
常用文件:favicon.ico、robots.txt、静态html模板、超大离线资源
使用规则:直接通过根路径 / 访问,不存放业务图片、动态资源
2. src/assets 目录(打包资源)
存放内容:需打包、哈希、压缩的项目资源,支持按业务拆分
assets/
├── images/ # 项目图片资源
│ ├── common/ # 全局通用图片
│ └── [模块名]/# 模块专属图片
├── fonts/ # 自定义字体文件
└── styles/ # 全局样式文件
├── reset.scss # 浏览器默认样式重置
├── var.scss # 全局颜色、尺寸、主题变量
└── global.scss # 全局通用样式3. api 目录(接口层)
核心原则:业务模块化拆分,禁止所有接口写在一个文件
存放内容:axios封装、请求拦截器、各业务模块接口函数
api/
├── request.ts # axios实例封装、拦截器、统一错误处理
├── login.ts # 登录、注册、退出接口
├── user.ts # 用户管理相关接口
├── goods.ts # 商品模块接口
└── order.ts # 订单模块接口
规范要求:页面仅调用接口函数,禁止在页面直接编写axios请求4. composables 目录(Vue3通用逻辑)
定位:替代mixins,抽离可复用的组合式业务逻辑,无DOM依赖
命名规范:统一 useXxx.ts 格式
composables/
├── useUser.ts # 用户信息、登录状态、权限逻辑
├── useTable.ts # 表格分页、查询、重置通用逻辑
├── useDialog.ts # 弹窗打开/关闭、表单重置逻辑
└── usePermission.ts # 页面、按钮权限判断逻辑5. directives 目录(自定义指令)
存放内容:全局通用DOM指令,复用性强的原生操作
常用指令:按钮权限、图片懒加载、拖拽、防抖、复制
6. layouts 目录(全局布局)
定位:项目页面外层外壳,不属于业务页面,全局统一布局
layouts/
├── MainLayout.vue # 后台主体布局(侧边栏+头部+内容区)
└── LoginLayout.vue # 登录页独立简洁布局
使用场景:路由配置中引入布局,嵌套渲染业务页面7. plugins 目录(第三方插件)
定位:统一注册、初始化第三方依赖,避免main.ts臃肿
常用插件:Element Plus、Vant、ECharts、SVG图标、统计埋点
8. router 目录(路由管理)
router/
├── index.ts # 路由实例、全局守卫、权限拦截
└── modules/ # 大型项目模块化拆分路由
├── system.ts
├── goods.ts
└── order.ts9. stores 目录(Pinia状态管理)
核心原则:按业务模块拆分,单一仓库单一职责
stores/
├── user.ts # 用户token、信息、权限全局状态
├── app.ts # 全局配置(侧边栏折叠、loading、主题)
└── goods.ts # 商品模块全局缓存数据10. types 目录(TS类型)
存放内容:全局接口、枚举、通用类型、全局声明
拆分规范:按业务模块拆分d.ts文件,统一全局类型约束
11. utils 目录(工具函数)
定位:纯JS/TS方法,无Vue依赖、无业务耦合,全局通用
utils/
├── format.ts # 时间、金额、日期格式化
├── validate.ts # 正则校验(手机号、邮箱、密码)
├── storage.ts # 本地存储封装
└── common.ts # 通用基础方法12. views 目录(业务页面)
核心定位:所有可路由访问的完整业务页面,一个路由对应一个页面模块
重要规范:页面私有组件,统一放在当前页面的 components 文件夹,不全局挂载
views/
├── system/ # 系统管理模块
│ ├── user/list/
│ │ ├── index.vue
│ │ └── components/ # 页面私有组件
│ └── role/
├── goods/ # 商品业务模块
└── order/ # 订单业务模块四、核心重点:components 目录最全规范
1. components 存放规则
✅ 允许存放
- 全局基础原子组件(按钮、弹窗、表格、输入框等)
- 多页面复用的通用业务组件(用户选择器、商品卡片、状态标签等)
- 全局通用UI组合组件(页面头部、SVG图标、空状态等)
- ❌ 禁止存放
- 完整业务页面(统一放views)
- 仅单个页面使用的一次性组件(放对应views内部components)
- 纯逻辑hooks、工具方法、接口请求
2. components 内部分层结构(标准通用)
components/
├── base/ # 基础原子组件(无业务、纯UI封装)
│ ├── BaseButton/
│ ├── BaseDialog/
│ ├── BaseTable/
│ └── BaseSearch/
├── business/ # 业务通用组件(带业务逻辑、多页面复用)
│ ├── UserSelect/
│ ├── GoodsCard/
│ └── OrderStatusTag/
└── common/ # 全局组合组件(布局、图标、通用模块)
├── PageHeader/
└── SvgIcon/3. 组件命名 & 文件规范(强制统一)
文件夹命名:统一 大驼峰 PascalCase
组件入口文件:固定 index.vue
可选导出文件:index.ts 统一导出,简化引入路径
组件前缀规范:
- 基础组件:前缀 Base(BaseDialog、BaseTable)
- 业务组件:业务名词大驼峰(UserSelect、GoodsCard)
- 禁止格式:小驼峰、短横线、下划线命名
五、极简目录(小型项目/H5/官网)
页面少、逻辑简单、无复杂权限,可删减冗余目录,保留核心能力
src/
├── api/
├── assets/
├── components/
├── composables/
├── router/
├── utils/
├── views/
├── App.vue
└── main.ts六、通用工程规范(统一落地)
1. 路径别名:统一配置 @ 指向 src 根目录,规避相对路径混乱
2. 样式规范:所有组件开启 scoped 样式隔离,全局样式统一管理
3. 代码分层:页面只做渲染,复杂逻辑全部抽离至composables
4. 复用原则:一次性逻辑写页面,多次复用抽离组件/hooks