目录结构怎么放最顺手
新项目一开始最容易出现两种极端:
- 什么都塞进
pages/,后面越写越乱 - 一上来就设计十几层目录,结果团队没人记得住
更稳的做法是:先用一个足够清晰、又不过度设计的结构跑起来。
一个推荐的起步结构
如果你现在准备做的是一个正常业务小程序,可以先从下面这个结构开始:
txt
src/
├─ app.vue
├─ app.json
├─ pages/
│ ├─ home/
│ │ └─ index.vue
│ └─ order/
│ ├─ list.vue
│ └─ detail.vue
├─ components/
│ ├─ product-card/
│ │ └─ index.vue
│ └─ empty-state/
│ └─ index.vue
├─ stores/
│ ├─ user.ts
│ └─ cart.ts
├─ services/
│ ├─ request.ts
│ ├─ user.ts
│ └─ order.ts
├─ utils/
│ ├─ formatPrice.ts
│ └─ time.ts
└─ assets/
├─ images/
└─ icons/它背后的分工很简单:
pages/放页面入口,一个页面一个目录或一个主文件components/放会复用的业务组件或通用组件stores/放状态管理,不要把接口请求、页面渲染和状态都揉在一起services/放请求封装和领域 APIutils/放纯工具函数assets/放跨页面复用的静态资源
页面目录里建议放什么
一个页面最常见的落位方式是:
txt
pages/order-detail/
├─ index.vue
├─ components/
│ └─ goods-item.vue
└─ useOrderDetail.ts页面局部的内容可以尽量贴近页面放,这样好处是:
- 打开页面目录就能看到完整上下文
- 页面下线时,局部组件和组合逻辑也能一起删掉
- 不会把全局
components/变成“公共垃圾场”
比如:
vue
<!-- pages/order-detail/index.vue -->
<script setup lang="ts">
import GoodsItem from './components/goods-item.vue'
import { useOrderDetail } from './useOrderDetail'
const { detail, loading } = useOrderDetail()
</script>什么时候放到全局 components/
满足下面两个条件,再考虑提升到全局:
- 确实被多个页面复用
- 组件本身已经有稳定的输入输出边界
例如这些通常适合放全局:
empty-stateprice-textloading-viewuser-avatar
而这种更适合留在页面目录:
order-status-cardcoupon-dialogrefund-reason-panel
services 和 stores 不要混
一个非常常见的问题是:把请求、缓存、页面 loading、错误提示全塞进页面里。
更推荐的分法是:
ts
// services/order.ts
export async function getOrderDetail(id: string) {
return request<OrderDetail>({
url: `/api/orders/${id}`,
})
}ts
// stores/order.ts
import { ref } from 'wevu'
import { getOrderDetail } from '../services/order'
export function useOrderStore() {
const detail = ref<OrderDetail | null>(null)
const loading = ref(false)
async function fetchDetail(id: string) {
loading.value = true
try {
detail.value = await getOrderDetail(id)
}
finally {
loading.value = false
}
}
return {
detail,
loading,
fetchDetail,
}
}一句话理解:
services负责和服务端对话stores负责把状态组织给页面消费
文件命名建议
从长期维护角度,建议一开始就统一:
- 页面目录:语义化、稳定,尽量不要频繁改路径
- 组件目录:
kebab-case - 工具函数文件:
camelCase - store 名称:按业务域命名,不要做成“超级 store”
例如:
txt
components/product-card/index.vue
stores/cart.ts
services/order.ts
utils/formatPrice.ts新用户最容易踩的目录坑
1. 所有内容都放全局
结果是:
- 小组件越来越多
- 页面上下文越来越难找
- 复用和“看起来像复用”混在一起
2. 所有内容都放页面目录
结果是:
- 公共组件没有真正抽象出来
- 同一逻辑在不同页面复制粘贴
3. 过早拆成特别复杂的领域层
如果你的项目还没超过几个核心业务页面,就不必一上来设计太复杂的模块边界。
一句话建议
先让结构服务于“能快速定位代码”,而不是服务于“看起来很高级”。
你现在可以继续看: