导读:本期聚焦于香港程序员创作的《Vue 3 企业级项目目录结构如何设计?一套可落地的工程化模板详解》,敬请观看详情。为什么团队越大,Vue 3 项目越容易变成一堆难以维护的文件夹堆砌?答案往往藏在目录结构设计上。本文从工程化角度出发,给出一套可直接落地的企业级 Vue 3 项目目录模板,涵盖按业务模块划分的 views 与 components 目录、统一管理的 api 层、可复用的 composables 组合式函数、集中式路由与状态管理方案,以及环境配置与代码规范工具的接入方式。文章还对比了按文件类型分层与按业务领域分模块两种组织方式的优劣,并结合权限系统、多环境构建等真实场景说明如何扩展,帮助中型以上团队在项目初期就建立起清晰的分层边界,避免后期重构成本失控。

目录结构看似只是文件夹摆放问题,实际上它决定了团队协作的边界、代码复用的成本以及后续重构的难度。Vue 3 项目如果一开始没有一个清晰的工程化结构,随着业务膨胀,很快就会出现组件随意放置、接口调用散落各处、公共逻辑复制粘贴等问题。本文给出一套经过实践验证的企业级 Vue 3 项目目录结构模板,并解释每个分层背后的设计考量。

Vue 3 企业级项目目录结构如何设计?一套可落地的工程化模板详解

一、整体目录结构模板

先看整体结构,基于 Vite 创建的 Vue 3 + TypeScript 项目,目录大致如下:

vue3-admin/
├── public/                  # 静态资源,不参与构建
├── src/
│   ├── api/                 # 接口请求层,按业务模块拆分
│   ├── assets/              # 样式、图片等资源
│   ├── components/          # 全局通用组件
│   ├── composables/         # 组合式函数
│   ├── directives/          # 自定义指令
│   ├── layouts/             # 布局组件
│   ├── router/              # 路由配置
│   ├── stores/              # Pinia 状态仓库
│   ├── styles/              # 全局样式与变量
│   ├── utils/               # 纯函数工具库
│   ├── views/               # 页面级组件,按业务域分组
│   ├── App.vue
│   └── main.ts
├── .env.development         # 开发环境变量
├── .env.production          # 生产环境变量
├── vite.config.ts
└── package.json

这个结构的核心思想是职责单一:每个目录只承担一类职责,api 目录不写 UI 逻辑,views 目录不放可复用组件,utils 目录保持纯函数不依赖 Vue 运行时。这样即使新人加入团队,也能通过文件路径快速判断某段代码应该放在哪里。

需要注意的是,src 下的目录数量要控制。一些小项目会把 axios 封装、权限判断、字典缓存全部塞进 utils,导致 utils 变成垃圾抽屉。建议凡是依赖 Vue 响应式系统的逻辑,优先放到 composables;凡是与后端交互的,放到 api;utils 只保留 formatDate、deepClone 这类无副作用的纯函数。

二、按文件类型分层还是按业务领域分模块

这是目录设计中最常见的争论。按文件类型分层(上面模板的方式)把所有页面放 views、所有组件放 components;按业务领域分模块则是每个业务域内部自带自己的 views、components、api,形成一个个垂直切片。

两种方式的对比可以看下表:

维度按类型分层按业务领域分模块
适合团队规模中小型团队大型团队、多小组并行
跨业务复用直观,公共组件集中需要额外的共享层
模块内聚性较弱,改动散落多处强,可整体迁移删除
上手成本较高,需要约定边界

实践中推荐的做法是分层为主、域内分组为辅:顶层保持按类型分层的结构,但在 views 和 api 内部按业务域建子目录。例如 views/system/user、views/system/role、views/finance/order,对应的接口文件放在 api/system/user.ts、api/finance/order.ts。这样既保留了公共组件的集中管理,又让业务边界在目录上一目了然。

当项目规模进一步扩大,比如超过五十个页面、多个小组各自负责不同业务线时,可以再演进为按领域分模块,在 src/modules 下按业务域组织完整切片,顶层目录只保留真正全局的东西。

三、关键目录的详细设计与示例

api 层:统一请求入口

api 层的价值在于把接口的 URL、参数、返回类型集中管理,页面不直接拼接请求地址。配合 TypeScript 可以给每个接口定义请求和响应类型:

// src/api/system/user.ts
import request from '@/utils/request'
import type { UserInfo, UserQuery } from './types'

// 获取用户分页列表
export function getUserList(params: UserQuery) {
  return request.get<UserInfo[]>('/api/system/users', { params })
}

// 新增用户
export function createUser(data: Omit<UserInfo, 'id'>) {
  return request.post<UserInfo>('/api/system/users', data)
}

页面组件中只导入函数调用,不感知 URL 细节。接口变更时只需改这一个文件,全项目受益。request 的实例封装(拦截器、token 注入、错误提示)放在 utils/request.ts 中,与具体业务解耦。

composables:组合式函数抽取

Vue 3 的组合式 API 让逻辑复用从 mixin 时代的主观约定变成了显式函数。命名上建议统一以 use 开头,一个文件只导出一个函数:

// src/composables/usePagination.ts
import { reactive } from 'vue'

export function usePagination(fetchFn: (params: any) => Promise<any>) {
  const pagination = reactive({ page: 1, pageSize: 10, total: 0 })

  async function loadData() {
    const res = await fetchFn({ page: pagination.page, pageSize: pagination.pageSize })
    pagination.total = res.total
    return res.list
  }

  function handlePageChange(page: number) {
    pagination.page = page
    return loadData()
  }

  return { pagination, loadData, handlePageChange }
}

任何列表页都可以复用这套分页逻辑,页面只需传入自己的请求函数。判断一段逻辑是否值得抽成 composable 的标准很简单:它是否同时涉及状态和方法,且会被两个以上页面使用。

router 与 stores 的组织

路由建议拆分为 index.ts(路由实例与守卫)加 modules 子目录(各业务模块的路由片段),并开启懒加载:

// src/router/modules/system.ts
import type { RouteRecordRaw } from 'vue-router'

export default [
  {
    path: '/system',
    component: () => import('@/layouts/BasicLayout.vue'),
    meta: { requiresAuth: true, title: '系统管理' },
    children: [
      {
        path: 'user',
        name: 'SystemUser',
        component: () => import('@/views/system/user/index.vue'),
        meta: { title: '用户管理' },
      },
    ],
  },
] as RouteRecordRaw[]

Pinia 仓库同样按业务域拆分文件,用户信息、权限、字典缓存各自独立 store,避免出现一个巨大的全局 store。meta 字段中还可以携带权限标识,供路由守卫做按钮级和页面级权限控制。

四、工程化配套:别名、环境变量与规范

目录结构只是骨架,还需要工程化配置来保证它被严格执行。首先在 vite.config.ts 中配置 @ 别名指向 src,并让 TypeScript 的 paths 配置保持一致:

// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitevite/plugin-vue'
import { fileURLToPath, URL } from 'node:url'

export default defineConfig({
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url)),
    },
  },
})

环境变量通过 .env.development 和 .env.production 区分接口地址等配置,代码中用 import.meta.env.VITE_API_BASE_URL 读取。凡是自定义变量必须以 VITE_ 开头,否则不会暴露给客户端代码,这是新手常踩的坑。

最后是规范工具:ESLint 负责代码质量规则,Prettier 统一格式化风格,再配合 eslint-plugin-vue 处理模板写法,husky 与 lint-staged 在提交前自动校验。还可以约定文件命名规则,比如组件目录用 kebab-case、composables 文件用 camel-case,写进团队文档并在 CI 中用脚本检查。

总的来说,目录结构没有唯一正确答案,但边界清晰、约定先行、随规模演进这三条原则是通用的。项目初期用分层结构快速起步,业务膨胀后向模块化演进,始终保持重构的空间,这才是企业级工程化模板的真正含义。

Vue3 目录结构工程化模板企业级前端架构修改时间:2026-09-01 14:46:41

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。