first commit

This commit is contained in:
xiang
2026-07-25 23:45:09 +08:00
commit c7bd957e6f
47 changed files with 3870 additions and 0 deletions
@@ -0,0 +1,146 @@
# Vue 核心代码规范
## 目录
- 技术风格与版本适配
- 命名与文件
- SFC 结构
- Props、Emits、Slots 与组件 API
- 响应式状态
- 模板
- TypeScript
- 异步与副作用
- 样式
- 注释与日志
- 官方依据
## 技术风格与版本适配
- 新建现代 Vue 3 SFC 时,优先使用 Composition API 与 `<script setup lang="ts">`
- 修改既有文件时,保持该模块的 API 风格;不要在一次无关功能变更中混合 Options API 和 Composition API。
- 使用 `defineModel`、响应式 props 解构、`useTemplateRef` 等能力前,核实项目 Vue 版本与团队惯例。
- 不使用实验性功能完成核心业务,除非项目已采用且存在回退或验证方案。
## 命名与文件
- 使用多单词组件名,避免与原生 HTML 元素冲突。
- 组件文件使用 `PascalCase.vue`,例如 `UserProfileCard.vue`
- 页面按项目约定使用 `*View.vue``*Page.vue`,不要在同一目录混用。
- composable 使用 `useXxx.ts`,并导出同名 `useXxx` 函数。
- Pinia store 使用 `useXxxStore`,每个 store 独立文件。
- 布尔变量使用 `is``has``can``should` 等前缀。
- 事件处理函数使用 `handleXxx`;传给 props 的回调可按项目约定使用 `onXxx`
- 类型、接口和泛型使用 `PascalCase`;不要默认增加 `I` 前缀。
- 常量使用项目既有约定;仅真正跨模块、不可变的常量使用全大写形式。
- 测试文件放在目标代码旁或项目统一测试目录,命名保持 `.spec.ts``.test.ts` 的既有选择。
## SFC 结构
默认保持以下顶层顺序:
```vue
<script setup lang="ts">
// imports
// types and component contracts
// injected dependencies, router and stores
// state
// computed values
// watchers and lifecycle
// handlers
</script>
<template>
<!-- declarative UI -->
</template>
<style scoped>
/* component-owned styles */
</style>
```
- 服从项目的 block 顺序和 import 排序规则。
- 仅在模板或组件逻辑实际需要时创建变量;不要为了分区制造空注释。
- 组件私有样式优先 `scoped` 或项目 CSS Modules 方案;主题、reset、tokens 和工具类保持全局。
- 避免使用 `:deep()` 穿透第三方或子组件内部;无法通过公开 API 定制时,记录耦合原因。
## Props、Emits、Slots 与组件 API
- 用类型声明组件契约,为可选 props 明确默认行为。
- props 名表示数据或状态;emits 名表示已发生的业务动作,例如 `submit``update:modelValue`
- 不以 emit 冒充命令式调用;父组件需要控制子组件时,优先 props 和状态驱动。
- 仅在确有命令式能力时使用 `defineExpose`,并保持暴露面最小。
- 为有双向语义的表单值使用 `v-model`/`defineModel`;普通业务数据继续使用 props + emits。
- 不直接解构会丢失响应性的对象。解构 Pinia 状态时使用 `storeToRefs`;解构一般响应式对象时按需使用 `toRefs`
- 为 slots 定义清晰语义;不要让父组件依赖子组件内部 DOM 结构。
- 可变对象或数组默认值必须保证实例隔离,并符合当前 Vue 版本支持的写法。
## 响应式状态
- 对基本类型和可整体替换的值使用 `ref`
- 对语义内聚且主要按属性更新的对象使用 `reactive`;不要创建巨大、无边界的响应式对象。
- 使用 `computed` 表达派生值,不将可推导数据复制进 state。
- 不在 `computed` 中发送请求、写 store、修改其他 state 或触发日志等副作用。
- 监听明确来源,避免无边界 deep watch;大型对象优先监听必要字段或规范化后的签名。
- 在 watcher 中处理异步时,取消或忽略过期结果,防止旧请求覆盖新状态。
- 对第三方实例、大型不可变结构或不需要深层代理的数据,评估 `shallowRef`/`markRaw`,但先用性能证据证明需要。
- composable 返回值需保持稳定且易解构;需要保护写入口时向外暴露 readonly state 与显式 mutation 函数。
## 模板
- 保持模板表达式简短且无副作用。
-`v-for` 提供稳定业务键;只有完全静态、永不重排的展示列表才可评估使用索引。
- 不在同一元素上组合 `v-if``v-for`;先计算筛选结果或使用外层 `<template>`
- 频繁切换且初始渲染可接受时评估 `v-show`;条件低频或初始成本高时使用 `v-if`
- 原生交互使用原生元素:动作使用 `<button>`,导航使用 `<a>`/`RouterLink`,不要用可点击 `<div>` 代替。
- 表单控件提供关联的 `<label>`、名称、错误提示和 disabled/loading 状态。
- 仅在确有 HTML 内容需求且输入经过可信净化时使用 `v-html`
- 对异步列表和页面显式渲染 loading、empty、error 和 success 状态。
- 使用 CSS 处理纯展示状态;不要用 JavaScript 复制 CSS 已能表达的响应式布局。
## TypeScript
- 遵守项目 `strict` 配置;新代码不得主动弱化类型检查。
- 优先类型推断,仅在公共边界、复杂返回值和可能误推断处显式标注。
- 使用 `unknown` 接收不可信值,并通过 schema、type guard 或判别字段收窄。
- 使用 `import type` 引入纯类型,避免无意义运行时依赖。
- 在 API、路由参数、storage、postMessage 等外部边界做运行时校验;TypeScript 类型不能验证运行时数据。
- 区分传输 DTO、领域模型和表单模型;存在语义差异时显式映射。
- 优先判别联合表达有限状态,避免多个互相矛盾的布尔值。
- 本地封闭集合优先联合类型或 `as const` 对象;是否使用 `enum` 服从项目约定。
- 避免 `as``!``@ts-ignore`。若第三方类型确有缺陷,局部封装并说明依据。
- 为泛型设置能表达用途的约束,不创建只为“显得通用”的泛型。
## 异步与副作用
- 让异步动作表达 loading、error 和 retry/恢复策略。
- 使用 `try/catch/finally` 保证状态复位;不要将所有异常统一转换为无信息的“失败”。
- 区分可展示业务错误、认证/权限错误、网络错误和程序缺陷。
- 搜索、联想和切页请求处理取消、去抖或响应顺序,防止竞态。
-`onUnmounted` 或 watcher cleanup 中释放事件监听、observer、timer、subscription 和请求。
- 不在模块顶层执行依赖浏览器、用户或实例生命周期的副作用。
- 对 SSR 项目避免在服务端路径直接访问 `window``document``localStorage`
## 样式
- 优先复用项目设计 tokens、组件库变量和现有布局原语。
- 不硬编码已有 token 表达的颜色、层级、间距、圆角或字号。
- 类名遵循项目既有 BEM、utility、CSS Modules 或其他约定。
- 避免高特异性、`!important` 和依赖 DOM 深度的选择器。
- 同时验证窄视口、文本放大、长内容、空内容和交互焦点。
- 尊重 `prefers-reduced-motion`,动画不应阻止操作或传达唯一信息。
## 注释与日志
- 注释解释“为什么、约束和权衡”,不要复述代码。
- 为公共 composable、复杂协议和非直观兼容性补充必要说明。
- 删除调试日志和断点。生产日志不得包含 token、个人信息、完整请求体或敏感业务数据。
- TODO 必须包含可操作条件或关联任务;不要留下无主 TODO。
## 官方依据
- [Vue 官方风格指南](https://vuejs.org/style-guide/)
- [Vue `<script setup>`](https://vuejs.org/api/sfc-script-setup.html)
- [Vue Composition API 与 TypeScript](https://vuejs.org/guide/typescript/composition-api)
- [Vue TypeScript 总览](https://vuejs.org/guide/typescript/overview)
- [`eslint-plugin-vue` 规则](https://eslint.vuejs.org/rules/)