很多人开始用 AI 写前端之后,会遇到一种奇怪的落差:
- 小 demo 里,AI 反应极快
- 一进真实 Vue 项目,输出质量立刻下降
- 文件越多、目录越复杂,它越容易改错地方
这并不神秘。
AI 在工程项目里的表现,很大程度上取决于仓库是否具备稳定的可读结构。对人来说,结构混乱只是“看着有点烦”;对 AI 来说,结构混乱意味着:
- 无法快速建立模块边界
- 无法判断哪些目录是职责核心
- 无法稳定推断“这个逻辑应该放在哪里”
所以这篇文章讲的不是“Vue 目录该长什么样才最优雅”,而是:
如果你的项目未来会持续使用 Cursor、Copilot 或其他 AI 助手,目录结构应该如何设计,才能让人和 AI 都更容易理解、更不容易误改?
先给结论:AI 友好的 Vue 项目,核心不是目录多漂亮,而是 4 个问题始终清楚
| 核心问题 | 目录结构要回答什么 | 做不好会怎样 |
|---|---|---|
| 页面放哪 | 路由与页面入口是否一眼可见 | AI 容易改到错误视图层 |
| 逻辑放哪 | 状态、请求、业务逻辑是否分层 | 组件越写越重,复用困难 |
| 共享资源放哪 | 公共组件、工具、类型是否集中 | 重复实现、命名冲突 |
| 禁区在哪里 | 哪些目录不能随便动 | AI 顺手改配置、依赖或全局样式 |
换句话说,AI 友好的本质不是“让机器开心”,而是把工程边界写进仓库结构。
为什么很多 Vue 项目一开始不乱,三个月后就开始难以协作
问题通常不是技术栈本身,而是项目随着迭代不断“局部最优”。
常见演化路径:
- 第一版页面简单,组件都写在一个目录里
- 后续需求增加,页面专属逻辑开始混进公共组件
- 状态逻辑和接口请求先写在页面里,之后来不及拆
- 复制一个旧文件最快,于是目录里开始出现多个“临时版本”
久而久之,目录虽然还叫 components、composables、stores,但真实语义已经变了。
这时人还能靠经验硬扛,AI 却会迅速失真,因为它主要依赖:
- 命名信号
- 目录关系
- 相邻文件模式
- 历史实现一致性
一旦这些线索相互冲突,它就更容易“从看起来像的地方下手”,而不是从真正应该修改的地方下手。
一个适合内容站、企业站与中小后台项目的基础目录骨架
下面这个骨架不是唯一标准,但非常适合 Vue 3 / Nuxt 3 / Nuxt 4 项目做长期协作。
app/
pages/ # 路由页面,只负责页面级组装
components/
ui/ # 通用基础组件
forms/ # 表单类组件
layout/ # 头部、页脚、导航等布局组件
pages/ # 页面专属区块组件
composables/ # 复用逻辑(不持久化状态)
middleware/ # 路由中间件
assets/ # 样式与静态资源引用
data/ # 常量、静态数据、映射表
stores/ # Pinia 状态层
server/
api/ # 服务端接口
utils/ # 服务端工具函数
content/ # 内容文件(如 Nuxt Content)
public/ # 直接公开访问的静态资源
这个结构的关键不在“目录多完整”,而在它把几个重要问题拆开了:
- 页面负责组装,不负责承载大量业务逻辑
- 可复用组件与页面专属区块分离
- 复用逻辑与持久状态分离
- 客户端与服务端语义分离
对于 AI 来说,这种结构的最大价值是:它能更稳定地推断修改边界。
页面层:pages/ 的职责必须收紧,不要变成第二个业务层
很多项目的问题,都是从页面层开始的。
页面层应该负责什么
- 路由入口
- 页面级数据组织
- 组件拼装
- 页面级 SEO 与埋点挂载
页面层不应该负责什么
- 大量表单校验细节
- 多接口聚合后的业务推导
- 跨页面共享状态管理
- 复杂 UI 细节样式抽象
如果页面层承担太多职责,AI 经常会误以为“这个页面文件就是业务真相”,从而在页面里越写越重。
更稳的做法是:
- 页面文件尽量短
- 页面文件主要承担“连接器”角色
- 页面中的具体区块逻辑,下沉到
components/pages/或composables/
如果你正在做建站类页面,也可以参考:Vue + Tailwind 落地页工作流。
组件层:把“通用组件”与“页面区块”分开,是最划算的长期投资
这是 AI 友好目录里最容易被忽视的一点。
为什么只用一个 components/ 容易出问题
因为时间一长,你会同时往里面塞入:
- 基础按钮、卡片、输入框
- 首页 Hero、定价区、案例区
- 登录弹窗、筛选栏、文章列表
这些组件的复用级别完全不同,但目录层面没有任何区分,AI 只能靠文件名猜职责。
更合理的拆法
| 目录 | 适合放什么 | AI 能得到的信号 |
|---|---|---|
components/ui/ | Button、Card、Badge、Input | 这里是通用基础层 |
components/forms/ | 表单字段、校验容器 | 表单相关行为集中 |
components/layout/ | Header、Footer、Sidebar | 全局结构相关 |
components/pages/ | HeroSection、FaqSection | 页面专属区块,不要误当通用组件 |
这样做的一个直接好处是:
- 让 AI 更容易知道“这次要改的是页面局部还是公共基础层”
- 减少它为了完成局部目标去误改全局组件的概率
逻辑层:composables/、stores/、server/ 一定要语义分明
这是最影响后续维护与 AI 输出稳定性的地方。
composables/ 负责什么
适合放:
- 可复用的交互逻辑
- 页面局部行为封装
- 无持久化要求的状态组合
- 纯前端派生逻辑
例如:
useLocaleSwitcherusePageSeouseEditorSelection
stores/ 负责什么
适合放:
- 跨页面共享状态
- 生命周期长于单个页面的状态
- 明确需要被观察与调试的状态
例如:
- 用户登录信息
- 全局主题模式
- 编辑器会话状态
server/ 负责什么
适合放:
- API 路由
- 服务端数据聚合
- 访问密钥或后端能力封装
这三层最容易混淆的地方
| 错误做法 | 为什么危险 |
|---|---|
| 在组件里直接写复杂请求逻辑 | UI 与业务耦合,AI 易重复实现 |
| 在 store 里堆页面局部状态 | 状态范围变大,后续难收口 |
| 把 server 逻辑复制进 composable | 客户端/服务端职责混乱 |
AI 在这种混层项目里,最常见的错误就是“在看起来最近的文件里补逻辑”,而不是在正确的层里实现。
命名规则比你想象的重要:AI 很依赖文件名与路径语义
很多人低估了命名对 AI 的影响。
对于人来说,list.vue、index.vue、data.ts 看几分钟也能摸清;对于 AI 来说,这类文件名会显著降低可推断性。
更推荐的命名策略
- 页面文件:按路由语义命名
- 组件文件:按角色命名,而不是按视觉效果命名
- composable:统一
useXxx - store:统一
useXxxStore - server api:按业务对象与动作命名
两种命名的差异
| 弱命名 | 强命名 |
|---|---|
list.vue | ArticleList.vue |
modal.vue | LeadCaptureModal.vue |
data.ts | pricingPlans.ts |
helper.ts | formatPublishDate.ts |
强命名的价值不只是更整洁,而是它能让:
- 搜索更快
- review 更快
- AI 更容易定位真实职责
目录边界写进规则里,才能避免“结构明明存在,AI 却还是乱改”
仅有目录结构还不够。
因为 AI 不会自动知道:
- 哪些目录能改
- 哪些目录不能碰
- 哪些文件只允许新增,不允许重构
所以建议把结构边界同步写进规则文件,例如:
- pages/ 只做页面级组装,不堆业务逻辑
- components/ui/ 视为公共基础层,修改需谨慎
- components/pages/ 允许页面定制,不要求全局复用
- stores/ 仅放跨页面共享状态
- server/api/ 不与客户端 composables 混用
- 不修改 package.json 与全局配置,除非任务明确要求
如果你正在用 Cursor,这一步尤其重要,可参考:Cursor Rules 模板库。
一个很实用的“AI 友好度”判断方法:看任务能不能只改对一层
你可以拿一个真实任务做自测:
“给联系页新增企业微信二维码入口,但不要影响全局 footer。”
一个结构清晰的项目里,AI 更可能定位到:
- 某个页面区块组件
- 对应静态数据或文案映射
- 必要时的局部 composable
而不是改到:
- 全局 layout
- 公共 Button
- 无关的表单组件
- 全站 Footer
如果你的仓库经常让 AI 做后一种事,说明目录结构没有把边界表达清楚。
失败案例:为什么很多 Vue 项目后来都变成“所有文件都像能改一下”
场景
一个项目最初只有几个页面,所有组件都放在 components/ 下,状态也主要写在页面文件里。
随着功能增加:
- 公共组件和业务组件混在一起
- store 开始保存页面局部状态
- 同一个接口逻辑既出现在页面里,也出现在 composable 里
- 若干旧版本文件为了“先别删”被保留
后果
团队自己已经难以快速判断:
- 这个问题该改页面、组件还是 store
- 这个组件是公共的还是临时的
- 这个逻辑的真相到底在哪个文件
AI 面对这样的仓库时,输出就会越来越像“猜测式维修”。
修复方式
不是一次性大重构,而是分阶段收口:
- 先把
components/ui/与components/pages/分开 - 再把页面里的复用逻辑抽到
composables/ - 再把真正跨页状态迁移到
stores/ - 最后补规则文件,明确边界
一个适合团队执行的目录治理顺序
第一阶段:先治理命名
因为命名成本最低,但收益很快体现。
第二阶段:再治理组件分层
优先把公共基础组件与页面区块拆开。
第三阶段:最后治理逻辑归位
把页面里过重的逻辑逐步迁到 composable、store 或 server 层。
这个顺序的好处是:
- 风险较低
- 每一轮都可单独 review
- AI 能立刻从更清晰的信号里获益
如果你还在犹豫 Vue 是否适合当前建站项目,也可以对照:前端框架选型完整指南 与 Vue 建站快路径。
Checklist:AI 友好的 Vue 项目目录,至少满足这些条件
- 页面入口与区块组件职责分明
- 通用组件与页面专属组件已分层
-
composables/、stores/、server/语义清晰 - 目录命名与文件命名具备明确业务语义
- 页面层不过度承载复杂业务逻辑
- 公共基础层有清晰的修改边界
- 规则文件中已写明哪些目录可改、哪些不可动
- 新同学或 AI 可以快速判断“某类改动应该落在哪一层”
- 大部分常见任务能在 3~5 个文件内完成
- 仓库不会让人和 AI 同时陷入“哪里都像入口”的状态
FAQ
1. 目录越细是不是越好?
不是。过度拆分也会让查找成本上升。关键不是目录数量,而是职责是否稳定、是否能帮助人和 AI 快速判断边界。
2. 小项目也需要这么认真分层吗?
至少要做最基础的分层。因为小项目往往会在某个时刻突然长大,越晚整理,迁移成本越高。
3. 我们已经有历史包袱,能一步到位重构吗?
通常不建议。更现实的方式是按命名、组件分层、逻辑归位这三个阶段逐步治理。
4. 这套方法只适合 Cursor 吗?
不只适合 Cursor。它同样适用于 Copilot、代码 review、团队 onboarding,以及后续维护。


