告别 AI 乱码!Vue3+TS 项目的 AI 编码助手规范实践

大家好,作为前端开发者,我们都在享受 AI 编码助手(如 Cursor、OpenCode)带来的效率提升。但你是否也遇到过:AI 生成的代码风格混乱、命名不统一、TypeScript 类型缺失、甚至引入项目中从未用过的依赖?这些问题不仅没有提升效率,反而增加了大量的 Code Review 成本。

今天,我就分享一套经过实战打磨的Vue 3 + TypeScript 项目 AI 编码助手规则集,它能帮你从源头约束 AI 行为,让 AI 生成的代码从第一行就符合团队规范,真正做到 "拿来就能用"。


一、为什么需要给 AI 制定 "员工手册"?

AI 编码助手就像一个新入职的实习生:它能力很强,但完全不了解你的项目约定。如果不给它明确的规则,它就会按照自己的 "通用常识" 写代码,结果往往是:

  • 风格不统一:一会儿 PascalCase,一会儿 camelCase
  • 依赖满天飞:不管项目用的 UI 库,强行引入新组件
  • 类型 any 泛滥:把 TypeScript 写成了 AnyScript
  • 架构混乱:无视项目目录结构,到处创建文件

解决这些问题的根本方法,就是给 AI 制定一套清晰、可执行的 "行为准则",让它在你的项目里也能像老员工一样 "守规矩"。


二、我的 Vue 项目 AI 规则集全景

我将规则分为了 4 个核心文件,覆盖了从通用行为到具体编码细节的所有场景:

  1. .agents/rules/common.md:通用编码规范(Vue3+TS 基础约定)
  2. .agents/rules/vue.md:Vue 3 组件专属规范
  3. .agents/rules/css.md:样式编写规范(BEM 命名等)
  4. .agents/rules/agent.md:AI 助手通用行为准则

下面我为你逐一拆解每个文件的核心内容与设计思路。


📄 1. 通用编码规范 (common.md)

这是整个规则集的基础,定义了所有代码都必须遵守的 "宪法级" 约定。

核心规则概览

表格

模块 关键约定
基础规范 路径别名遵循tsconfig配置;单文件不超过 400 行;注释清晰
命名规范 组件名PascalCase;函数camelCase;常量UPPER_SNAKE_CASE
TypeScript 优先interface;禁止滥用anyprops默认值用withDefaults
导入与排序 按「类型导入 → 第三方库 → Vue 官方库 → 项目内部」分组
目录组织 遵循components/views/composables/stores约定
最佳实践 组件优先复用 UI 库;响应式优先用ref/computed;重复逻辑下沉

关键设计亮点

  • 强约束的命名规则:AI 对命名的理解往往很模糊,这里直接规定死:

    • 组件名必须是PascalCase(如UserCard.vue
    • 事件处理函数必须带handle前缀(如handleSubmit
    • 组合式函数必须带use前缀(如useUserList
  • TypeScript 安全锁 :明确禁止滥用any,并强制使用withDefaults定义props默认值,从源头杜绝类型安全问题。

  • 防重复造轮子:要求 AI 优先复用项目内已有组件、工具函数,避免引入新依赖。


📄 2. Vue 3 组件专属规范 (vue.md)

这是针对 Vue 单文件组件(SFC)的 "专项约束",解决 AI 生成 Vue 代码时最容易出错的问题。

核心规则概览

  • 强制 Composition API :新组件必须使用<script setup lang="ts">,禁止 Options API

  • 固定代码块顺序templatescript setupstyle

  • Script 内部顺序约定

    1. 类型导入 import type
    2. 第三方库 / UI 组件
    3. Vue API(ref/reactive/computed等)
    4. 项目内模块导入
    5. defineProps/defineEmits等编译器宏
    6. 响应式数据、方法、生命周期钩子
  • 关键 API 使用规范

    • defineEmits必须使用基于类型的函数调用签名,禁止数组 / 元组形式
    • 获取组件实例优先使用useTemplateRef(Vue3.3+)
    • defineExpose仅暴露父组件必须调用的方法 / 属性

关键设计亮点

  • SFC 结构标准化:很多 AI 生成的 Vue 文件结构混乱,这里直接规定了代码块和内部逻辑的顺序,保证所有组件结构一致。
  • 响应式规则 :明确约定 "原始值用ref,对象用reactive,派生状态用computed",避免 AI 写出低效的响应式代码。
  • 禁止项明确 :列出了 AI 最容易犯的错误,如重复导入已自动注册的组件、用JSON.parse(JSON.stringify())做深拷贝等。

📄 3. 样式编写规范 (css.md)

AI 写 CSS 时最容易放飞自我,比如随便命名 class、滥用!important、写出嵌套过深的选择器。这个文件就是用来 "驯服" AI 的样式代码。

核心规则概览

  • BEM 命名强制约定

    • Block:user-card(双下划线连接,禁止驼峰)
    • Element:user-card__avatar(双下划线连接)
    • Modifier:user-card--compact(双横杠表示状态)
  • SFC 样式块规范 :默认使用scoped,必须覆盖第三方样式时需注释说明

  • 编写原则 :优先使用项目 CSS 变量;避免魔法数字;禁止滥用!important

  • 禁止项

    • class 使用camelCase命名
    • BEM 元素链式嵌套(如block_a__b
    • scoped样式中依赖深度选择器穿透多层级

关键设计亮点

  • BEM 命名可执行化 :不仅介绍 BEM,还直接给出了scoped中结合 SCSS 嵌套的写法示例,让 AI 知道怎么写才对。
  • 防污染控制 :强制使用scoped,并对穿透样式做严格限制,避免全局样式污染。
  • 反模式清单:明确列出了 AI 写 CSS 的常见错误,让它从一开始就避开这些坑。

📄 4. AI 助手行为准则 (agent.md)

这是给 AI 助手本身制定的 "元规则",控制它的行为边界,防止它越权操作。

核心规则概览

  • 通用要求:始终使用简体中文沟通;未经允许不创建文档、不执行 Git 操作
  • 应当做的:改代码前阅读项目约定;优先复用已有抽象;修改后运行 lint/typecheck
  • 不应当做的:擅自新增说明文档;为已自动导入的 API 写冗余 import;猜测不存在的 API 路径

关键设计亮点

  • 边界控制:明确禁止 AI 执行 Git 操作、修改配置文件等危险行为,保证开发者对项目的绝对控制权。
  • 效率优先:禁止 AI 做 "多余的事",比如在没有要求的情况下添加测试、注释或文档,避免干扰开发者的节奏。

三、如何在项目中落地这套规则?

步骤 1:创建规则文件目录

在项目根目录创建.agents/rules/文件夹,将上面 4 个文件放入其中。

plaintext

erlang 复制代码
.
├── .agents/
│   └── rules/
│       ├── common.md
│       ├── vue.md
│       ├── css.md
│       └── agent.md

步骤 2:配置 Cursor Rules

在项目根目录创建.cursorrules文件,将所有规则文件串联起来:

markdown

yaml 复制代码
---
applyTo: "**"
---

# 项目编码规范

以下规则适用于本项目所有代码,请严格遵守:

## 通用编码规范
@./.agents/rules/common.md

## Vue 3 组件规范
@./.agents/rules/vue.md

## CSS 样式规范
@./.agents/rules/css.md

## AI 助手行为准则
@./.agents/rules/agent.md

步骤 3:让 AI "看见" 规则

  • 在 Cursor 中,AI 会自动读取.cursorrules文件
  • 在其他工具中,可以在每次对话时手动引用这些文件,或配置项目级别的全局指令

四、效果实测:AI 写代码的变化

在应用这套规则前后,AI 生成的代码质量有了质的变化:

表格

场景 规则前 规则后
组件命名 userCard.vue(驼峰) UserCard.vue(PascalCase)
Props 定义 const props = defineProps({ id: Number }) const props = withDefaults(defineProps<{ id?: number }>(), { id: 0 })
Class 命名 .headerTitle/.btn-primary .user-card__title/.user-card__btn--primary
API 调用 直接在组件中写 fetch 调用项目已封装的useApi组合式函数

五、总结与扩展

给 AI 制定编码规范,不是为了限制它的能力,而是为了让它的能力更好地服务于你的项目。这套规则集的核心价值在于:

  1. 统一团队代码风格:无论谁用 AI 写代码,输出的结果都能保持一致
  2. 降低 Code Review 成本:AI 生成的代码天然符合规范,减少不必要的风格争论
  3. 提升项目可维护性:TypeScript 类型更安全、架构更清晰、样式更可控
  4. 解放开发者精力:你不用再花时间修正 AI 的低级错误,可以专注于业务逻辑

💡 后续优化建议

  • 按需扩展:根据你的项目特性,添加更多项目特定规则,比如状态管理(Pinia)、路由、权限等
  • 定期更新:随着项目迭代,不断完善规则集,将团队的最佳实践沉淀进去
  • 团队共享:将这套规则同步给团队所有人,让 AI 成为统一的 "代码风格监督员"

如果你需要,我可以把这 4 个规则文件的完整 Markdown 内容整理出来,方便你直接复制使用。


觉得有用的话,欢迎点赞收藏,也欢迎在评论区分享你的 AI 编码规范实践!


附:规则文件完整模板(可直接复制)

.agents/rules/common.md

markdown

markdown 复制代码
# 编码规范 (Vue 3 + TypeScript)

适用于 Vue 3 + TypeScript 前端项目的通用编码约定。Vue SFC 细节见 `vue.md`,样式见 `css.md`。

## 基础规范
- 路径别名、目录结构遵循**项目既有配置**(如 `tsconfig`、`vite.config`);避免 `../../../../` 式相对路径穿越。
- `.vue` 文件与模板中的组件使用 **PascalCase**(`UserCard.vue` / `<UserCard />`)。
- 样式 class 推荐 **kebab-case**;组件内自定义 class 推荐 BEM(见 `css.md`)。
- 单文件建议不超过 400 行,超出应拆分组件或模块。
- 注释语言、标识符语言遵循项目约定;代码标识符使用英文,含义清晰。

## 命名规范
- **组件名**: PascalCase。
- **变量 / 函数**: camelCase;事件处理函数推荐 `handle` 前缀(如 `handleSubmit`)。
- **常量**: 需要时使用 UPPER_SNAKE_CASE。
- **Props / Emits**: props 用 camelCase;模板事件名与 emits 定义用 kebab-case。
- **Composables**: 推荐 `use` 前缀(如 `useUserList`)。
- **全局组件前缀**(如有): 遵循项目统一前缀,不要自创多套命名。

## TypeScript 规范
- `import type` 与值导入分离。
- 对象结构优先 `interface`;联合类型、工具类型用 `type`。
- 组件 props 默认值使用 `withDefaults(defineProps<Type>(), { ... })`。
- 避免 `any`;确实需要时使用显式类型或窄化。
- Composables、工具函数适当使用泛型提升类型安全。
- 公共类型集中管理;领域类型靠近业务模块,按项目目录约定放置。

## Vue 相关(摘要)
以下细则见 `vue.md`,此处不重复:
- Composition API + `<script setup>`
- `defineOptions` / `defineProps` / `defineEmits` / `defineExpose`
- 模板 ref、`v-model`、事件与插槽命名

## 导入与排序
推荐分组(同组内按字母序):
1.  类型导入
2.  第三方库
3.  Vue / 官方库
4.  项目内部(composables、组件、utils、样式、资源)

- 不要重复 import 已由自动导入注册的符号(类型除外)。
- 静态资源、样式按项目约定引入,避免大段内联样式。

## 目录与组织
- 遵循项目现有目录划分(如 `components`、`views`、`composables`、`stores` 等)。
- 可复用 UI 放组件目录;页面级逻辑解放 views 或路由对应模块。
- 跨页面逻辑抽到 composables;纯函数抽到 utils。
- 常量、枚举集中管理,避免魔法字符串散落。

## 代码质量与 Lint
- 遵循项目 **ESLint**、**Stylelint**、**tsconfig** 配置,不擅自关闭规则。
- 必要的 `eslint-disable` / `@ts-expect-error` 须注释说明原因。
- Vue 相关 lint(block 顺序、宏顺序、事件命名等)以项目 ESLint 配置为准。

## 最佳实践
- **组件封装**: 优先复用项目 UI 库与已有封装;透传 props / attrs 时保持 API 一致。
- **类型安全**: 接口、props、emits、composables 返回值均提供类型。
- **响应式**: 原始值用 `ref`,对象用 `reactive`,派生用 `computed`(详见 `vue.md`)。
- **性能**: 模板避免复杂计算;大列表考虑分页、虚拟滚动或拆分;按需加载路由与组件。
- **代码复用**: 重复逻辑下沉 composable 或 utils,不要复制粘贴。

## 提交流程与检查
- 包管理器与锁文件以仓库为准;变更依赖时同步更新 lockfile。
- 提交前按项目脚本执行检查(如 `lint`、`typecheck`、`test`、`build`)。
- 新文件默认带类型,避免无类型的 `any` 扩散。

.agents/rules/vue.md

markdown

markdown 复制代码
# Vue 规范 (Vue 3)

适用于 Vue 3 + Composition API + `<script setup>` 的组件开发约定。

## 基础要求
- 新组件一律使用 **Composition API** + `<script setup lang="ts">`,禁止 Options API。
- 需要组件名时(调试、keep-alive、路由缓存等)使用 `defineOptions({ name: 'ComponentName' })`。
- 路由级页面组件的 `name` 建议与路由配置保持一致。

## 组件块顺序
- `<template>` → `<script setup lang="ts">` → `<style>`(样式见 `.agents/rules/css.md`)
- 遵循项目 ESLint/Vue block-order 规则。

## Script 内推荐顺序
1.  类型导入 `import type ...`
2.  第三方库 / UI 组件
3.  Vue API(`ref`、`reactive`、`computed`、`watch` 等)
4.  项目内模块(composables、utils、components 等)
5.  `defineOptions`(如有)
6.  `defineModel`(如有)
7.  `defineProps` + `withDefaults`
8.  `defineEmits`(事件名 kebab-case)
9.  `defineSlots`(如有)
10. 常量 / 工具函数 / composables 解构
11. 响应式数据 `ref` / `reactive`
12. `computed` 派生数据
13. 方法(推荐 `handle` 前缀,如 `handleSubmit`)
14. 生命周期 / 副作用(`onMounted`、`watch` 等)
15. `defineExpose` 放最后(如需要)

## 自动导入
若项目配置了 `unplugin-auto-import`、`unplugin-vue-components` 等,**遵循项目已有约定**:
- 已自动注册的 API / 组件不要重复手写 import。
- 仅需**类型**时使用 `import type`。
- 不确定是否自动导入时,以项目 `vite.config` 与现有代码为准。

## 模板约定
- 模板保持单根节点(或遵循 Vue 3.3+ 多根节点的项目约定)。
- 事件名、插槽名使用 **kebab-case**。
- 受控表单优先 `v-model`;修饰符与命名参数按 Vue 3 语法书写。
- 布尔 prop / 双向绑定使用显式写法(如 `:visible="visible"`、`v-model:visible="visible"`)。
- 复杂列表/表格渲染可使用 `lang="tsx"` 或 render 函数,按项目既有模式选用。

## 组件注册与引用
- 全局 / 局部组件在模板中使用 **PascalCase**(如 `<UserCard />`)。
- 不要手动 import 已由自动导入注册的组件(类型导入除外)。
- 子组件通过 props / emits 通信,避免随意访问父组件实例。

## defineEmits
- 使用**基于类型的函数调用签名**,禁止数组 / tuple 形式。
- 无参事件: `(e: 'event-name'): void`;有参事件将参数写在 `e` 之后。

```typescript
// ✅
const emit = defineEmits<{
  (e: 'submit'): void
  (e: 'change', value: string): void
}>()

// ❌
const emit = defineEmits({ submit: [] })()
const emit = defineEmits<{ change: [value: string] }>()

模板 Ref

  • 获取子组件实例 或 DOM 元素时,优先使用 useTemplateRef (Vue 3.5+);低版本可用 ref + 同名模板 ref,与项目约定保持一致。
  • 模板上的 ref 属性值与 useTemplateRef('...') 参数字符串一致。

vue

xml 复制代码
<script setup lang="ts">
import type { FormInstance } from './types'
const formRef = useTemplateRef<FormInstance>('formRef')

function submit() {
  formRef.value?.validate()
}
</script>

<template>
  <form ref="formRef" @submit.prevent="submit">
    <!-- ... -->
  </form>
</template>

defineExpose

  • 仅暴露父组件组件确实需要调用的方法或属性。
  • 弹窗、表单等封装组件常用 defineExpose({ open, close, reset }) 模式。

响应式

  • 原始值用 ref,对象用 reactive;派生状态用 computed
  • 避免不必要的大对象 reactive;从 composable 返回时保持结构清晰。
  • 解构 reactive 对象时注意响应式丢失,必要时用 toRefs

禁止事项

  • 使用 Options API 编写新组件
  • 重复 import 已自动注册的 API / 组件(类型除外)
  • 用无关的 ref() 命名绑定模板 ref 导致语义混乱(优先 useTemplateRef
  • defineEmits 使用数组 /tuple 形式
  • 在模板中写复杂业务逻辑,应抽到 computed 或方法
  • 使用 JSON.parse(JSON.stringify()) 做深拷贝(优先 structuredClone 或项目提供的工具)

样式相关约定见 .agents/rules/css.md

plaintext

javascript 复制代码
#### `.agents/rules/css.md`
```markdown
# CSS 规范 (Vue 3)

适用于 Vue 3 单文件组件(SFC)的样式编写约定。

## SFC 样式块
- 样式块位于 `<script>` 之后:`<style lang="scss|less|css" scoped>`。
- 遵循项目的 ESLint/Vue block-order 规则(通常为 template → script → style)。
- 默认使用 **`scoped`**,避免污染全局;需要全局样式时须在注释中说明原因。
- 预处理器(SCSS/LESS)与纯 CSS 按项目既有约定选用,同一组件内保持一致。

## 命名约定
- 自定义 class 使用 **kebab-case**。
- 组件内自定义 class 推荐 **BEM**(Block Element Modifier)。
- 第三方 UI 库自带类名、项目全局工具类不在 BEM 约束范围内;仅约束本组件新增的 class。

## BEM 结构
| 类型 | 格式 | 示例 |
| :--- | :--- | :--- |
| Block(块) | `block` | `user-card`、`search-form` |
| Element(元素) | `block__element` | `user-card__avatar`、`search-form__input` |
| Modifier(修饰符) | `block--modifier` 或 `block__element--modifier` | `user-card--compact`、`search-form__btn--disabled` |

约定:
- **Block** 对应当前组件语义,一个 SFC 通常只设一个 Block。
- **Element** 用双下划线 `__` 连接 Block;多级语义用 `-` 连接,**禁止** `block__a__b` 链式元素写法。
- **Modifier** 用双连字符 `--` 表示状态或变体(如 `--active`、`--disabled`、`--compact`)。
- 在 `<style scoped>` 中优先用预处理器嵌套表达 BEM(`&__element`、`&--modifier`)。

```vue
<template>
  <div class="user-card">
    <img class="user-card__avatar" :src="avatar" alt="">
    <div class="user-card__body">
      <h3 class="user-card__name">{{ name }}</h3>
      <span class="user-card__badge user-card__badge--vip">VIP</span>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.user-card {
  display: flex;
  gap: 12px;

  &__avatar {
    width: 48px;
    height: 48px;
    border-radius: 50%;
  }

  &__name {
    margin: 0;
    font-size: 16px;
  }

  &__badge {
    font-size: 12px;

    &--vip {
      color: var(--color-warning, #faad14);
    }
  }
}
</style>

编写原则

  • 颜色、间距、字号优先复用项目 CSS 变量或设计令牌,避免魔法数字。
  • 动画与过渡可复用的,抽到公共样式;组件内只写与布局 / 状态相关的差异。
  • 避免内联 style;动态样式(如宽高、坐标)等场景除外。
  • 尽量避免 !important;确需覆盖第三方样式时注明原因。

Stylelint

  • 遵循项目已配置的 Stylelint 规则(如 standard、scss、recommended-vue、recess-order 等)。
  • 属性顺序以 Stylelint 输出为准;class 命名推荐 BEM/kebab-case。
  • 样式改动后按项目脚本执行 lint(如 lint:style)。

禁止事项

  • ❌ 自定义 class 使用 camelCase 或非语义命名(如 .headerTitle.activeBtn
  • ❌ BEM 元素链式嵌套(如 block__a__b,应扁平为 block__a-b
  • ❌ 滥用 !important 覆盖样式
  • ❌ 在组件内写大段内联 style(特殊动态样式除外)
  • ❌ 在 scoped 样式中依赖未声明的深度选择器穿透(:deep() 等)堆叠过多层级

plaintext

diff 复制代码
#### `.agents/rules/agent.md`
```markdown
# Agent 行为准则

适用于 Cursor、OpenCode、Codex 等 AI 编码助手。

## 通用要求
- 始终使用**简体中文**与用户沟通。
- 未经用户明确要求,**不要**创建说明文档(README、*.md 等)。
- 未经用户明确要求,**不要**执行 git commit / push / 修改 git 配置。
- 改动范围最小化:只改与任务直接相关的代码,不顺手重构无关模块。
- 优先复用项目已有抽象与约定,禁止凭空引入新架构或重复造轮子。

## 应当
- 改代码前先阅读项目既有实现与目录约定,保持风格一致。
- 优先复用项目内已有组件、composables、工具函数与 API 封装。
- 任务完成后,在合适时运行项目配置的 lint / typecheck / test 脚本(若与改动相关)。
- 存在分层文档或 skills 时,**按需读取**与当前任务相关的部分,不要预加载全部。

## 不应
- 擅自新增说明性 Markdown 文档(除非用户明确要求)。
- 为已自动导入的 API / 组件写冗余 import。
- 引入与项目技术栈不符的 UI 库或全新抽象层。
- 猜测不存在的 API 路径、响应结构或配置项;以项目代码与类型定义为准。
- 在用户未要求时添加测试、文档或无关注释。
相关推荐
踏雪羽翼2 小时前
android 实现文字打印机效果
android·前端·javascript
编程技术手记2 小时前
Vue Scoped CSS 与动态创建 DOM 的兼容性问题
前端·css·vue.js
Patrick_Wilson2 小时前
从「框架内部报错」到「请求头被网关截断」:一次 Sentry 排障与前端 Cookie 误用复盘
前端·http·浏览器
Cerrda2 小时前
从 uno.config.ts 看懂 UnoCSS 图标方案
前端·代码规范
甲维斯2 小时前
GLM5.1版“超级玛丽”,有点东西!
人工智能·ai编程·游戏开发
ANnianStriver2 小时前
PetLumina 06 — 图片上传全链路
java·ai·ai编程·文件上传·cos·腾讯云对象存储
shengjk12 小时前
AI时代的信息平权将不复存在
ai编程
爱勇宝2 小时前
《置身钉内》之后:普通前端的出路在哪里?
前端·后端·程序员
KaMeidebaby3 小时前
卡梅德生物技术快报|羊驼免疫:分子生物学实战:基于羊驼免疫的重链抗体制备与全流程验证方案
前端·网络·数据库·人工智能·算法·百度