使用 create-vue 或 npm create vue@latest 初始化项目后,你会得到一个标准的目录骨架。这个结构是社区长期实践沉淀下来的共识,不是死规定,但遵循它能降低团队沟通成本,让项目更容易维护。
标准目录结构一览
my-vue-app/
├── .vscode/ # VS Code 编辑器配置(可选)
├── node_modules/ # 依赖包
├── public/ # 静态资源,不经过构建处理
│ └── favicon.ico
├── src/
│ ├── assets/ # 需要构建处理的静态资源(图片、字体、样式)
│ ├── components/ # 公共组件
│ ├── composables/ # 组合式函数(自定义 Hooks)
│ ├── router/ # 路由配置
│ │ └── index.js
│ ├── stores/ # Pinia 状态管理
│ ├── views/ # 页面级组件(与路由对应)
│ ├── App.vue # 根组件
│ └── main.js # 应用入口文件
├── .gitignore
├── index.html # HTML 模板
├── package.json
├── vite.config.js # Vite 构建配置
└── README.md
各目录职责与使用说明
public/ —— 不参与构建的静态资源
这里的文件会原样复制到打包输出目录,路径直接基于根路径引用。适合放永远不会变动的资源,比如 favicon.ico、第三方库的静态文件,或者需要保持特定文件名的资源(如 robots.txt)。
<!-- index.html 中引用 public 下的资源 -->
<link rel="icon" href="/favicon.ico">
注意:public 下的资源不会被 Vite 处理,所以不会获得哈希文件名和路径优化。大多数图片、字体等资源应该放到 src/assets/ 下借助构建工具优化。
src/assets/ —— 需要构建处理的资源
CSS、图片、字体等资源放在这里,构建工具(Vite)会处理它们:小图片转 base64、添加文件哈希、压缩优化等。在组件或样式文件中通过相对路径或别名引入。
<template>
<img src="@/assets/logo.png" alt="logo">
</template>
src/components/ —— 可复用的公共组件
存放被多个页面或模块复用的“积木”式组件,比如 BaseButton.vue、DataTable.vue、ModalDialog.vue。命名通常采用 PascalCase。
如果项目规模较大,可以在 components/ 内部按功能或业务域再划分子目录,但初期不宜过度嵌套。
src/views/ —— 页面级组件
与路由一一对应,每个视图代表一个完整的页面。比如 HomeView.vue、UserProfileView.vue、ProductListView.vue。这些组件通常只负责页面布局和数据聚合,具体的 UI 细节由 components/ 中的组件完成。
src/composables/ —— 组合式函数(Hooks)
把可复用的逻辑抽成函数,以 use 开头命名。例如 useFetch.js 封装数据请求、useAuth.js 封装登录逻辑、usePagination.js 处理分页。这是 Vue 3 组合式 API 的核心复用单元,能让组件代码变得非常干净。
src/router/ —— 路由配置
集中管理所有路由规则,一个典型的 index.js 长这样:
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '@/views/HomeView.vue'
const routes = [
{ path: '/', component: HomeView },
{
path: '/products',
component: () => import('@/views/ProductListView.vue') // 懒加载
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
src/stores/ —— Pinia 状态管理
每个 Store 文件对应一个业务域的状态,例如 useUserStore.js 管理用户信息,useCartStore.js 管理购物车。Pinia 天然支持模块化,不需要像 Vuex 那样手动嵌套 modules。
src/App.vue —— 根组件
应用的顶层组件,通常只包含根布局结构(侧边栏、顶栏、路由视图容器):
<template>
<div id="app">
<AppHeader />
<router-view />
</div>
</template>
src/main.js —— 应用入口
在这里创建 Vue 应用实例,注册全局插件(路由、状态管理、全局组件、指令等),然后挂载到 DOM。
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import { createPinia } from 'pinia'
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.mount('#app')
最佳实践:避坑与提效
1. 组件命名:看名字就知道是干什么的
- 页面组件:
XxxView(或XxxPage),如UserListView。 - 通用组件:
Base前缀表示基础 UI 组件(BaseButton、BaseInput),其他用描述性名称(ProductCard、OrderTimeline)。 - 不要使用缩写,除非它是整个团队公认的。
2. 目录分层:按功能而非文件类型
早期项目不要一上来就建 api/、utils/、constants/ 等零散目录。当项目膨胀时,更推荐按业务模块组织:
src/
modules/
user/
components/
composables/
stores/
views/
product/
...
这种“模块化”结构能让一个功能的全部代码内聚在一起,查找和搬迁都很方便。
3. 善用路径别名
在 vite.config.js 中配置 @ 指向 src,避免到处写 ../../../:
// vite.config.js
import { defineConfig } from 'vite'
import path from 'path'
export default defineConfig({
resolve: {
alias: {
'@': path.resolve(__dirname, 'src')
}
}
})
4. 单文件组件结构顺序
一个 .vue 文件内部,推荐固定顺序:<template> → <script setup> → <style scoped>。这是一种约定俗成的阅读习惯,不要让团队成员在文件中来回滚动。
5. 不要过早优化目录结构
刚开始一个项目只有两三个页面时,views/ 和 components/ 就足够了。随着复杂度上升,再逐步引入 composables/、stores/、modules/ 等分层。目录结构是为开发效率服务的,不是为了满足“看起来专业”。