# Vue 核心代码规范 ## 目录 - 技术风格与版本适配 - 命名与文件 - SFC 结构 - Props、Emits、Slots 与组件 API - 响应式状态 - 模板 - TypeScript - 异步与副作用 - 样式 - 注释与日志 - 官方依据 ## 技术风格与版本适配 - 新建现代 Vue 3 SFC 时,优先使用 Composition API 与 ` ``` - 服从项目的 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`;先计算筛选结果或使用外层 ``。 - 频繁切换且初始渲染可接受时评估 `v-show`;条件低频或初始成本高时使用 `v-if`。 - 原生交互使用原生元素:动作使用 ``,导航使用 ``/`RouterLink`,不要用可点击 `` 代替。 - 表单控件提供关联的 ``、名称、错误提示和 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 `