【Vue3】【中后台前端开发】从【按业务域划分目录结构】到【落地实操】彻底搞懂【可维护前端代码】的最佳写法避开目录混乱、维护困难高频坑 文章目录一、开篇这篇文章能帮你解决什么问题二、常见的“反面教材”2.1 所有组件堆在components里2.2 只按技术类型划分2.3 嵌套过深三、核心思路按业务域划分3.1 什么是“业务域”3.2 这样划分的好处四、推荐的 Vue3 项目目录结构完整版4.1 各目录职责说明五、实战按业务域搭建一个简单项目5.1 目录规划5.2modules/user/types.ts5.3modules/user/api.ts5.4views/user/Login.vue六、常见坑与避坑建议6.1 组件该放components/还是views/xxx/components/6.2 API 放哪6.3 类型放哪6.4 路径别名6.5 循环依赖七、小结如何落地这套规范同学们好我是 Eugene尤金一名多年中后台前端开发工程师。Eugene 发音 /juːˈdʒiːn/大家怎么顺口怎么叫就好很多前端开发者都会遇到一个瓶颈代码能跑但不够规范功能能实现但维护起来特别痛苦一个人写没问题一到团队协作就各种混乱、踩坑、返工。想写出干净、优雅、可维护的专业代码靠的不是天赋而是体系化的规范 真实实战经验。这一系列《前端规范实战》我会用大白话 真实业务场景不讲玄学、不堆理论只分享能直接落地的规范、标准与避坑指南。帮你从「会写代码」真正升级为「会写优质、可维护、团队级别的代码」。一、开篇这篇文章能帮你解决什么问题工作里常见几类问题新人接手项目不知道功能写在哪页面一多文件到处散落难以维护团队各写各的命名、分层不统一改需求时要翻很多目录才能定位到相关代码这篇文章会围绕Vue3 项目按业务域划分的目录结构规范讲清楚为什么要这样分每个目录该放什么、不该放什么怎么从零搭建一个规范的目录常见坑点如何规避目标是看完就能照着做新人也能快速上手。二、常见的“反面教材”2.1 所有组件堆在components里src/ ├── components/ │ ├── UserCard.vue # 用户相关 │ ├── OrderList.vue # 订单相关 │ ├── ProductDetail.vue # 商品相关 │ ├── LoginForm.vue # 登录相关 │ ├── Header.vue │ ├── Footer.vue │ └── ...几十个组件混在一起问题业务一多components会变成大杂烩找文件、理清依赖都很费劲。⬆ 返回目录2.2 只按技术类型划分src/ ├── views/ # 全是页面 ├── components/ # 全是组件 ├── api/ # 全是接口 ├── utils/ # 全是工具函数问题和业务脱节。改“用户中心”要同时改views、components、api心智负担大。⬆ 返回目录2.3 嵌套过深src/ ├── modules/ │ └── user/ │ └── profile/ │ └── settings/ │ └── security/ │ └── SecurityForm.vue # 层级太深问题导入路径过长易出错也不利于理解整体结构。⬆ 返回目录三、核心思路按业务域划分3.1 什么是“业务域”业务域 产品里的一块独立功能/业务模块。例如用户登录、注册、个人中心、设置商品列表、详情、搜索订单下单、列表、详情营销活动、优惠券每个域包含页面、组件、接口、类型、工具等尽量聚合在一起。⬆ 返回目录3.2 这样划分的好处好处说明易于定位改“订单”就进order目录不用到处找易于协作不同人负责不同域冲突少易于复用模块边界清晰抽离公共能力更自然易于交接新人看目录就能大致理解业务结构⬆ 返回目录4、推荐的 Vue3 项目目录结构完整版src/ ├── api/ # 全局 API跨域、通用接口 │ └── request.ts # 封装 axios / fetch │ ├── assets/ # 静态资源 │ ├── images/ │ ├── styles/ │ │ ├── variables.scss # 变量 │ │ └── global.scss # 全局样式 │ └── fonts/ │ ├── components/ # 全局公共组件多域复用 │ ├── common/ # 通用 UI 组件 │ │ ├── AppButton.vue │ │ ├── AppModal.vue │ │ └── AppTable.vue │ └── layout/ # 布局组件 │ ├── AppHeader.vue │ ├── AppSidebar.vue │ └── AppFooter.vue │ ├── composables/ # 全局可复用组合式函数 │ ├── useAuth.ts # 鉴权 │ ├── usePagination.ts # 分页 │ └── useTable.ts # 表格 │ ├── router/ │ └── index.ts # 路由配置 │ ├── store/ # Pinia 状态 │ └── index.ts # 根 store 或全局模块 │ ├── types/ # 全局类型 │ └── common.ts │ ├── utils/ # 全局工具 │ ├── format.ts │ ├── storage.ts │ └── validate.ts │ ├── views/ # 路由页面按业务域划分子目录 │ ├── user/ # 用户域 │ │ ├── Login.vue │ │ ├── Register.vue │ │ ├── Profile.vue │ │ └── components/ # 仅本域使用的组件 │ │ └── ProfileForm.vue │ ├── product/ # 商品域 │ │ ├── List.vue │ │ ├── Detail.vue │ │ └── components/ │ │ └── ProductCard.vue │ └── order/ # 订单域 │ ├── List.vue │ ├── Detail.vue │ └── components/ │ └── OrderStatus.vue │ ├── modules/ # 业务域模块页面外的逻辑、API、类型 │ ├── user/ │ │ ├── api.ts # 用户相关接口 │ │ ├── types.ts # 用户相关类型 │ │ └── store.ts # 用户相关 store可选 │ ├── product/ │ │ ├── api.ts │ │ └── types.ts │ └── order/ │ ├── api.ts │ └── types.ts │ ├── App.vue └── main.ts4.1 各目录职责说明目录职责放什么不放什么api/请求封装、全局接口axios 实例、拦截器、跨域请求具体业务接口assets/静态资源图片、样式、字体逻辑代码components/全局组件多域复用 UI、布局只在某一域用的组件composables/全局组合式函数鉴权、分页、表格等单页面内用的逻辑router/路由路由配置业务组件store/全局状态跨域共享的状态单域状态建议放modules/xxx/store.tstypes/全局类型通用 TS 类型业务域专用类型utils/全局工具格式化、校验、存储业务逻辑views/路由页面按业务域分组非页面组件modules/业务域逻辑接口、类型、单域 store视图组件⬆ 返回目录五、实战按业务域搭建一个简单项目5.1 目录规划views/user/Login.vue # 登录页 modules/user/api.ts # 登录接口 modules/user/types.ts # 用户类型 components/common/AppInput.vue # 通用输入框若复用⬆ 返回目录5.2modules/user/types.ts// 用户相关类型定义exportinterfaceLoginParams{username:stringpassword:string}exportinterfaceUserInfo{id:numberusername:stringavatar:stringtoken:string}⬆ 返回目录5.3modules/user/api.ts// 用户相关接口 - 集中管理方便维护importrequestfrom/api/requestimporttype{LoginParams,UserInfo}from./typesexportconstloginApi(data:LoginParams){returnrequest.postUserInfo(/api/user/login,data)}exportconstgetUserInfoApi(id:number){returnrequest.getUserInfo(/api/user/${id})}⬆ 返回目录5.4views/user/Login.vuetemplatedivclasslogin-pageh1用户登录/h1formsubmit.preventhandleLogininputv-modelform.usernametypetextplaceholder用户名/inputv-modelform.passwordtypepasswordplaceholder密码/buttontypesubmit:disabledloading登录/button/formpv-iferrorMsgclasserror{{ errorMsg }}/p/div/templatescriptsetuplangtsimport{ref,reactive}fromvueimport{useRouter}fromvue-routerimport{loginApi}from/modules/user/apiimporttype{LoginParams}from/modules/user/typesconstrouteruseRouter()constloadingref(false)consterrorMsgref()constformreactiveLoginParams({username:,password:})consthandleLoginasync(){if(!form.username||!form.password){errorMsg.value请填写完整信息return}loading.valuetrueerrorMsg.valuetry{constresawaitloginApi(form)// 存储 token 等逻辑...router.push(/profile)}catch(e:any){errorMsg.valuee.message||登录失败}finally{loading.valuefalse}}/scriptstylescoped.login-page{max-width:400px;margin:50px auto;padding:20px;}.error{color:red;font-size:14px;}/style说明要点页面只负责「展示 调用接口」接口在modules/user/api.ts类型在modules/user/types.ts修改接口或类型时只需改对应模块页面改动小⬆ 返回目录六、常见坑与避坑建议6.1 组件该放components/还是views/xxx/components/只有当前业务域会用→ 放views/xxx/components/至少两个域会用到→ 放components/common/或components/layout/⬆ 返回目录6.2 API 放哪只服务于某一域→modules/xxx/api.ts跨域或基础能力→api/或单独抽一层如api/base.ts⬆ 返回目录6.3 类型放哪仅该域使用→modules/xxx/types.ts多处复用→types/common.ts或共享的types/模块⬆ 返回目录6.4 路径别名在vite.config.ts或vue.config.js里配置// vite.config.ts 示例resolve:{alias:{:path.resolve(__dirname,src)}}这样可以用/modules/user/api代替../../../modules/user/api。⬆ 返回目录6.5 循环依赖modules/user/api.ts引用storestore又引用api容易形成循环。建议API 层不依赖 storestore 调用 api或通过 composable 间接调用⬆ 返回目录七、小结如何落地这套规范新项目先按业务域规划views/和modules/再写代码。老项目可先从新功能开始按域拆分逐步迁移旧代码。团队把目录规范写到文档或.cursor/rules里新人 onboarding 时统一讲解。核心原则高内聚、低耦合——同一业务域的代码尽量在一起跨域共用部分放到components、utils、composables等全局目录。⬆ 返回目录技术成长从来不是比谁写得快而是比谁写得稳、规范、可维护。哪怕每次只吃透一条规范长期下来差距会非常明显。后续我会持续更新前端规范、工程化、可维护代码相关实战干货帮你告别面条代码、维护噩梦在开发与面试中更有底气。觉得有用欢迎点赞 收藏 关注不错过每一篇实战内容。我是 Eugene与你一起写规范、写优质代码我们下篇干货见
Vue3 项目目录结构规范:按业务域划分,新人快速上手|项目规范篇
发布时间:2026/5/24 22:45:35
【Vue3】【中后台前端开发】从【按业务域划分目录结构】到【落地实操】彻底搞懂【可维护前端代码】的最佳写法避开目录混乱、维护困难高频坑 文章目录一、开篇这篇文章能帮你解决什么问题二、常见的“反面教材”2.1 所有组件堆在components里2.2 只按技术类型划分2.3 嵌套过深三、核心思路按业务域划分3.1 什么是“业务域”3.2 这样划分的好处四、推荐的 Vue3 项目目录结构完整版4.1 各目录职责说明五、实战按业务域搭建一个简单项目5.1 目录规划5.2modules/user/types.ts5.3modules/user/api.ts5.4views/user/Login.vue六、常见坑与避坑建议6.1 组件该放components/还是views/xxx/components/6.2 API 放哪6.3 类型放哪6.4 路径别名6.5 循环依赖七、小结如何落地这套规范同学们好我是 Eugene尤金一名多年中后台前端开发工程师。Eugene 发音 /juːˈdʒiːn/大家怎么顺口怎么叫就好很多前端开发者都会遇到一个瓶颈代码能跑但不够规范功能能实现但维护起来特别痛苦一个人写没问题一到团队协作就各种混乱、踩坑、返工。想写出干净、优雅、可维护的专业代码靠的不是天赋而是体系化的规范 真实实战经验。这一系列《前端规范实战》我会用大白话 真实业务场景不讲玄学、不堆理论只分享能直接落地的规范、标准与避坑指南。帮你从「会写代码」真正升级为「会写优质、可维护、团队级别的代码」。一、开篇这篇文章能帮你解决什么问题工作里常见几类问题新人接手项目不知道功能写在哪页面一多文件到处散落难以维护团队各写各的命名、分层不统一改需求时要翻很多目录才能定位到相关代码这篇文章会围绕Vue3 项目按业务域划分的目录结构规范讲清楚为什么要这样分每个目录该放什么、不该放什么怎么从零搭建一个规范的目录常见坑点如何规避目标是看完就能照着做新人也能快速上手。二、常见的“反面教材”2.1 所有组件堆在components里src/ ├── components/ │ ├── UserCard.vue # 用户相关 │ ├── OrderList.vue # 订单相关 │ ├── ProductDetail.vue # 商品相关 │ ├── LoginForm.vue # 登录相关 │ ├── Header.vue │ ├── Footer.vue │ └── ...几十个组件混在一起问题业务一多components会变成大杂烩找文件、理清依赖都很费劲。⬆ 返回目录2.2 只按技术类型划分src/ ├── views/ # 全是页面 ├── components/ # 全是组件 ├── api/ # 全是接口 ├── utils/ # 全是工具函数问题和业务脱节。改“用户中心”要同时改views、components、api心智负担大。⬆ 返回目录2.3 嵌套过深src/ ├── modules/ │ └── user/ │ └── profile/ │ └── settings/ │ └── security/ │ └── SecurityForm.vue # 层级太深问题导入路径过长易出错也不利于理解整体结构。⬆ 返回目录三、核心思路按业务域划分3.1 什么是“业务域”业务域 产品里的一块独立功能/业务模块。例如用户登录、注册、个人中心、设置商品列表、详情、搜索订单下单、列表、详情营销活动、优惠券每个域包含页面、组件、接口、类型、工具等尽量聚合在一起。⬆ 返回目录3.2 这样划分的好处好处说明易于定位改“订单”就进order目录不用到处找易于协作不同人负责不同域冲突少易于复用模块边界清晰抽离公共能力更自然易于交接新人看目录就能大致理解业务结构⬆ 返回目录4、推荐的 Vue3 项目目录结构完整版src/ ├── api/ # 全局 API跨域、通用接口 │ └── request.ts # 封装 axios / fetch │ ├── assets/ # 静态资源 │ ├── images/ │ ├── styles/ │ │ ├── variables.scss # 变量 │ │ └── global.scss # 全局样式 │ └── fonts/ │ ├── components/ # 全局公共组件多域复用 │ ├── common/ # 通用 UI 组件 │ │ ├── AppButton.vue │ │ ├── AppModal.vue │ │ └── AppTable.vue │ └── layout/ # 布局组件 │ ├── AppHeader.vue │ ├── AppSidebar.vue │ └── AppFooter.vue │ ├── composables/ # 全局可复用组合式函数 │ ├── useAuth.ts # 鉴权 │ ├── usePagination.ts # 分页 │ └── useTable.ts # 表格 │ ├── router/ │ └── index.ts # 路由配置 │ ├── store/ # Pinia 状态 │ └── index.ts # 根 store 或全局模块 │ ├── types/ # 全局类型 │ └── common.ts │ ├── utils/ # 全局工具 │ ├── format.ts │ ├── storage.ts │ └── validate.ts │ ├── views/ # 路由页面按业务域划分子目录 │ ├── user/ # 用户域 │ │ ├── Login.vue │ │ ├── Register.vue │ │ ├── Profile.vue │ │ └── components/ # 仅本域使用的组件 │ │ └── ProfileForm.vue │ ├── product/ # 商品域 │ │ ├── List.vue │ │ ├── Detail.vue │ │ └── components/ │ │ └── ProductCard.vue │ └── order/ # 订单域 │ ├── List.vue │ ├── Detail.vue │ └── components/ │ └── OrderStatus.vue │ ├── modules/ # 业务域模块页面外的逻辑、API、类型 │ ├── user/ │ │ ├── api.ts # 用户相关接口 │ │ ├── types.ts # 用户相关类型 │ │ └── store.ts # 用户相关 store可选 │ ├── product/ │ │ ├── api.ts │ │ └── types.ts │ └── order/ │ ├── api.ts │ └── types.ts │ ├── App.vue └── main.ts4.1 各目录职责说明目录职责放什么不放什么api/请求封装、全局接口axios 实例、拦截器、跨域请求具体业务接口assets/静态资源图片、样式、字体逻辑代码components/全局组件多域复用 UI、布局只在某一域用的组件composables/全局组合式函数鉴权、分页、表格等单页面内用的逻辑router/路由路由配置业务组件store/全局状态跨域共享的状态单域状态建议放modules/xxx/store.tstypes/全局类型通用 TS 类型业务域专用类型utils/全局工具格式化、校验、存储业务逻辑views/路由页面按业务域分组非页面组件modules/业务域逻辑接口、类型、单域 store视图组件⬆ 返回目录五、实战按业务域搭建一个简单项目5.1 目录规划views/user/Login.vue # 登录页 modules/user/api.ts # 登录接口 modules/user/types.ts # 用户类型 components/common/AppInput.vue # 通用输入框若复用⬆ 返回目录5.2modules/user/types.ts// 用户相关类型定义exportinterfaceLoginParams{username:stringpassword:string}exportinterfaceUserInfo{id:numberusername:stringavatar:stringtoken:string}⬆ 返回目录5.3modules/user/api.ts// 用户相关接口 - 集中管理方便维护importrequestfrom/api/requestimporttype{LoginParams,UserInfo}from./typesexportconstloginApi(data:LoginParams){returnrequest.postUserInfo(/api/user/login,data)}exportconstgetUserInfoApi(id:number){returnrequest.getUserInfo(/api/user/${id})}⬆ 返回目录5.4views/user/Login.vuetemplatedivclasslogin-pageh1用户登录/h1formsubmit.preventhandleLogininputv-modelform.usernametypetextplaceholder用户名/inputv-modelform.passwordtypepasswordplaceholder密码/buttontypesubmit:disabledloading登录/button/formpv-iferrorMsgclasserror{{ errorMsg }}/p/div/templatescriptsetuplangtsimport{ref,reactive}fromvueimport{useRouter}fromvue-routerimport{loginApi}from/modules/user/apiimporttype{LoginParams}from/modules/user/typesconstrouteruseRouter()constloadingref(false)consterrorMsgref()constformreactiveLoginParams({username:,password:})consthandleLoginasync(){if(!form.username||!form.password){errorMsg.value请填写完整信息return}loading.valuetrueerrorMsg.valuetry{constresawaitloginApi(form)// 存储 token 等逻辑...router.push(/profile)}catch(e:any){errorMsg.valuee.message||登录失败}finally{loading.valuefalse}}/scriptstylescoped.login-page{max-width:400px;margin:50px auto;padding:20px;}.error{color:red;font-size:14px;}/style说明要点页面只负责「展示 调用接口」接口在modules/user/api.ts类型在modules/user/types.ts修改接口或类型时只需改对应模块页面改动小⬆ 返回目录六、常见坑与避坑建议6.1 组件该放components/还是views/xxx/components/只有当前业务域会用→ 放views/xxx/components/至少两个域会用到→ 放components/common/或components/layout/⬆ 返回目录6.2 API 放哪只服务于某一域→modules/xxx/api.ts跨域或基础能力→api/或单独抽一层如api/base.ts⬆ 返回目录6.3 类型放哪仅该域使用→modules/xxx/types.ts多处复用→types/common.ts或共享的types/模块⬆ 返回目录6.4 路径别名在vite.config.ts或vue.config.js里配置// vite.config.ts 示例resolve:{alias:{:path.resolve(__dirname,src)}}这样可以用/modules/user/api代替../../../modules/user/api。⬆ 返回目录6.5 循环依赖modules/user/api.ts引用storestore又引用api容易形成循环。建议API 层不依赖 storestore 调用 api或通过 composable 间接调用⬆ 返回目录七、小结如何落地这套规范新项目先按业务域规划views/和modules/再写代码。老项目可先从新功能开始按域拆分逐步迁移旧代码。团队把目录规范写到文档或.cursor/rules里新人 onboarding 时统一讲解。核心原则高内聚、低耦合——同一业务域的代码尽量在一起跨域共用部分放到components、utils、composables等全局目录。⬆ 返回目录技术成长从来不是比谁写得快而是比谁写得稳、规范、可维护。哪怕每次只吃透一条规范长期下来差距会非常明显。后续我会持续更新前端规范、工程化、可维护代码相关实战干货帮你告别面条代码、维护噩梦在开发与面试中更有底气。觉得有用欢迎点赞 收藏 关注不错过每一篇实战内容。我是 Eugene与你一起写规范、写优质代码我们下篇干货见