人人都会AI编程

2.2 标准项目目录结构与最佳实践

更新时间:2026-07-11

使用 create-vuenpm 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.vueDataTable.vueModalDialog.vue。命名通常采用 PascalCase

如果项目规模较大,可以在 components/ 内部按功能或业务域再划分子目录,但初期不宜过度嵌套。

src/views/ —— 页面级组件

与路由一一对应,每个视图代表一个完整的页面。比如 HomeView.vueUserProfileView.vueProductListView.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 组件(BaseButtonBaseInput),其他用描述性名称(ProductCardOrderTimeline)。
  • 不要使用缩写,除非它是整个团队公认的。

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/ 等分层。目录结构是为开发效率服务的,不是为了满足“看起来专业”。