Vue 3 + TypeScript 通用开发规范(质量下限 + 安全)
定位与全局观
- 适用范围:任意 Vue 3 + TypeScript 前端(中后台、数据看板、埋点 SDK/管理端、安全监测、官网、低代码宿主等)。具体业务子目录命名(如
views/order与views/mall)由 README / 项目级规则 规定;本节「目录与模块边界」规定通用分层职责与依赖方向,与业务域名称无关。UI 组件库选型由项目自行约定。 - 对 AI / 开发者的期望:交付物应稳定可维护(判空、错误态、契约清晰)、安全合规(密钥与敏感数据)、结构清晰(可拆分、可演进)。无论产品是「订单」还是「事件上报」,同一套下限均适用。
- 与 README 的关系:接口成功判定、业务错误码、HTTP 语义以
README.md为准(第二节)。环境变量命名前缀、文件上传限制、错误上报方式、a11y 达标要求等若与「行业默认」不同,也应在 README 或 README 链接的文档中写明;本规则只写原则,不写死具体工具与阈值。 - 原则:不得低于目标仓库已有 根目录工程基座(见第五节:ESLint、Prettier、Stylelint、TypeScript、
vue-tsc、Commitlint 等)所定义的基线;只允许同等或更严。上不封顶。
目录与模块边界(通用)
目标:任意接手仓库的人(含 AI)能判断「新文件该放哪、谁能依赖谁」,避免跨域耦合与循环依赖。
1. 推荐 src/ 分层职责
以下目录名为常见约定;若仓库使用 pages/ 代替 views/、stores/ 代替 store/ 等,等价映射即可,但职责应一致。
| 目录 | 职责 |
|---|---|
api/ | 仅 HTTP 调用、请求/响应类型;禁止写页面状态、路由、业务 UI 分支。按后端域或业务域分子目录。 |
views/ 或 pages/ | 路由级页面;可含本页专用子组件、本页 composable(或迁入 hooks/ / composables/)。 |
components/ | 跨页面复用的展示与交互;宜再分 基础/通用 与 业务共享(子目录或命名前缀区分),避免业务细节污染底层组件。 |
hooks/、composables/ | 可复用的组合式逻辑(请求+状态、表单、表格等),无路由耦合为佳。 |
store/、stores/ | 全局或跨路由会话态;禁止把仅单页使用的列表状态默认升仓,除非 README 约定。 |
router/ | 路由表、守卫、元信息;禁止在路由文件内写大块业务逻辑,应委托 composable/store。 |
utils/ | 纯函数、与组件实例无关的工具;禁止依赖具体页面或 router 单例(特殊封装除外并在 README 说明)。 |
types/ | 全局 TS 类型、.d.ts;领域类型优先靠近使用方或 api/ 同模块。 |
assets/ | 图片、字体等静态资源。 |
config/、plugins/、directives/、layout/、locales/ 等 | 按项目既有结构放置;新增类目录须在 README 或项目规则 中记一笔,避免一人一套。 |
典型 src/ 目录树(任意 Vue 3 + TypeScript 项目均可采用;业务子目录名由 README 自定)
以下为与业务无关的参考骨架;views 与 api 下的下一级文件夹(如 order、admin、telemetry)不在此写死,由 README 列出「域 ↔ 路径」映射即可。
src/
├── api/ # 按业务域/资源分子目录;仅 HTTP 与类型
├── assets/ # 静态资源
├── components/ # 跨页复用组件(可再分子目录:base、business 等)
├── composables/ # 或 hooks/,任选其一或并存但职责不重复
├── config/ # HTTP 客户端、应用级配置(可选,依项目)
├── constants/ 或 constant/ # 全局常量、枚举映射(可选,与 types 区分)
├── directives/ # 自定义指令(可选)
├── layout/ 或 layouts/ # 壳层布局(可选)
├── locales/ # 或 i18n/(可选)
├── plugins/ # Vue 插件注册(可选)
├── router/ # 路由
├── store/ 或 stores/ # 全局状态(可选)
├── styles/ # 全局样式(可选)
├── types/ # 全局类型
├── utils/ # 纯工具函数
└── views/ 或 pages/ # 路由页面;域级子目录与 api/ 对齐
- 小型项目可删减空目录;大型项目可增加
services/、constants/、lib/等,但须在 README 说明职责,且不破坏上文依赖方向。 - Monorepo 子应用:每个应用各自具备完整或精简的
src/,本节约束按应用根生效。
2. 组织策略(二选一为主,全仓库一致)
- 按技术分层:
api/*、views/*、components/*清晰分离;适合中后台与多域并列。 - 按功能域(feature):
features/order/{api,components,pages}等;适合域边界强、团队按域分工。
混合时须约定:域内可就近放子文件,域间共享须通过 components/、hooks/、api/ 等公共层,禁止 views/domainA 深层 import views/domainB 的内部实现文件。
3. 依赖方向(必须)
- 单向依赖:页面 →(api / hooks / components / store)→ utils / types;禁止
utils→views、api→views、子业务页 → 另一业务页内部文件。 - 禁止明显 循环依赖(A→B→A);出现时用 类型-only import、拆共享模块或下沉
utils解决。 - 路径别名(如
@/)仅缩短路径,不改变上述分层语义。
4. api/ 与页面
- 同一后端资源:api 模块与 views 模块在目录命名上应对齐(具体命名表见 README 或项目级规则)。
- 页面内禁止手写裸
axiosURL 字符串散落;必须经统一客户端与 api/ 内函数(与第二节 README 契约一致)。
5. barrel 文件(index.ts 聚合导出)
- 谨慎在大型目录根使用 barrel 再导出全部,易引发 循环引用 与 tree-shaking 变差;优先 按需路径导入 或 有限导出列表。若项目统一使用 barrel,须在 README 说明规范。
6. 与 README / 项目规则的关系
- 本文件:规定「放什么类代码、谁依赖谁」及通用
src/骨架;适用于所有 Vue 3 + TypeScript 仓库(拷贝时勿删本节)。 - README(或各仓库自己的项目级规则):规定路径别名、业务域文件夹命名(
api/<域>与views/<域>对照表)、以及本仓库相对上图的增删目录。 - 冲突时:结构纪律以更严、更贴近本仓库 README 者为准。
7. public/ 与 src/assets/(应用根目录下,与 src/ 并列,通用)
public/(Vite 等约定名,或构建工具等价目录):构建时原样输出到站点根,不经模块打包与按内容哈希重命名。适用于favicon、robots.txt、需固定 URL** 供外链/第三方回调引用的文件。在模板或 HTML 中通常用 根相对路径(如/logo.svg),**不要**按 ES 模块import。src/assets/:经import/ SFC 引用 进入依赖图,可享受 文件名哈希、压缩、按需 等构建优化。适用于 组件内图片、与打包相关的资源。- 禁止将本可受益于打包管线的大资源误放
public/导致体积与缓存策略失控;禁止将须稳定不变路径的文件误放src/assets/导致部署后 URL 变化破坏外链。例外须在 README 写明。
一、硬性禁止(违反即视为不合格)
1. 空值与类型安全
- 禁止在未判空/未收窄类型的情况下访问嵌套属性或调用方法(
a.b.c、arr[0].x;可选链能表达意图时优先使用)。 - 禁止用
as粗暴断言掩盖未校验的数据结构;确需断言时应已有运行时校验或明确的不变式说明。 any:默认禁止;仅在第三方类型缺失等窄场景使用,且应局限在最小范围(并优先考虑unknown+ 校验/收窄)。
2. 模板与指令
- 禁止在同一元素上同时使用
v-if与v-for。应改为:外层template v-for+ 内层v-if,或先用计算属性/过滤后的列表渲染。 v-for:必须提供稳定、可预测的:key(优先业务主键;避免仅用索引,除非静态列表且无副作用)。
3. 结构与可维护性
- 禁止单函数过长(建议 ≤ 80 行为常态上限;超过应拆分)。严禁单函数数百行。
- 禁止单文件组件无节制膨胀(建议
.vue≤ 400 行为警戒;超过应拆子组件、composables、纯模块)。严禁单文件上千行堆叠。 - 禁止在
setup或单一函数中混杂无关职责(I/O、领域规则、展示状态搅在一起);应分层或拆分。
大文件拆分顺序(必须):先抽 composables(状态、异步与数据契约、领域规则),再抽 展示型子组件。禁止只拆模板、核心逻辑仍堆在父组件。
4. 异步、接口与状态
- 禁止在未确认「本次调用在约定意义上成功且载荷可用」时,直接使用业务字段驱动核心 UI。
- 禁止忽略 loading / 错误态 / 空数据态,导致静默失败或误导。
- 禁止无意义的空
catch;须记录、兜底 UI 或按统一策略向上抛出。
5. 反例模式(领域无关)
以下属于不合格:请求返回后不先按项目约定判断成功与否,仅按「像数组或带 list/data」猜测结构就当作有效数据使用。
// 反例:未按统一成功判定,易把失败响应当列表用
const res = await api.getList()
const list = Array.isArray(res) ? res : (res?.list ?? res?.data ?? [])
合格方向:先按 README.md(或 README 指向的契约文档) 与 HTTP 客户端/拦截器实际行为 判定成功,再读取载荷,并对数组/对象做校验与默认值。
6. 路由与 URL 输入
route.params、route.query及任何来自 URL 的字符串视为不可信输入;用于 跳转、拼请求、权限判断 前必须校验格式与取值范围(正则、白名单、与当前会话上下文比对等,细节以 README 为准)。- 禁止将 query 中的
redirect、完整 URL、外链 等未经验证与白名单即用于window.location或router.push,防止开放重定向。 - 数字/枚举类 ID:转换后须校验有效(如
Number.isFinite、正整数、UUID 格式等按 README),再发起请求。
7. 写操作与重复提交
- 创建、更新、支付、提交表单等写操作:请求进行中必须通过 loading + 禁用触发控件 或等价互斥锁,禁止因连点、双击、重复触发导致并发重复提交。
- 若 README/后端约定 幂等键(Idempotency-Key) 等机制,必须按约定携带;禁止在未读契约时自行发明不一致的 header/body 字段名。
8. 高风险载荷的运行时校验
- 对 README 中列出或团队公认的高风险路径(如资金、权限、安全策略、关键配置、不可逆操作的数据依赖):在 HTTP 成功之后、驱动核心业务之前,必须做 运行时形状校验(
zod/valibot/ 手写守卫等,工具以 README 为准)。校验失败须走错误分支,禁止当成功路径继续渲染或提交。 - 禁止仅依赖 TypeScript
as或「猜字段」消费上述载荷。
二、接口与响应契约(以 README 为准)
本节不写死具体数值或字段名;唯一事实来源为仓库 README.md 中与后端/API 相关的约定(成功码、失败形态、错误提示字段、不存在资源时的 HTTP 行为等)。若契约写在其它文件,README 须指向该文件,AI 与开发者实现前必须先读。
必须遵守的纪律(与具体码值无关):
- 禁止在未阅读 README 契约的情况下,凭猜测拼接「可能是
list/data/数组」来使用响应。 - 必须按 README 约定区分:HTTP/网络层失败 与 业务层失败(含各自如何提示用户);二者不得混用一种处理方式导致重复提示或静默失败。
- 若响应体含业务成功/失败标识(如
code、success等,以 README 为准):须在能访问到该字段时按 README 判断;禁止在失败语义下仍把载荷当成功数据驱动核心 UI。 - 若 HTTP 客户端 拦截器 在失败时
reject、成功时 unwrap 只返回data:调用方仍须理解「等价于已在拦截器侧按 README 判定成功」,禁止在契约未澄清时假设 unwrap 结果一定可用。 - 禁止假设列表载荷一定为数组;须
Array.isArray或 README 约定的类型守卫后再迭代。 - README 缺失或契约含糊:应先补写 README 或与维护者对齐后再写接口消费代码,禁止长期依赖未文档化的口头约定。
三、安全与数据边界(必选)
- 密钥与凭证:禁止在源码、规则、注释、提交记录中硬编码 token、密码、私钥;使用环境变量或构建注入;含秘密的
.env*不得提交版本库。 - 配置与环境变量:禁止在业务代码中写死生产基址、环境差异大的开关等;须从 构建时环境变量 或 README 约定的运行时配置接口读取。仓库必须提供可提交的
.env.example(或 README 中的变量表),列出变量名、含义、是否必填与占位示例,不得包含真实秘密;新增配置须先更新 example/文档再写代码(变量前缀如VITE_*等以 README 为准)。 - XSS:用户可控内容须按项目方案处理(默认转义、
v-html与富文本须白名单/消毒);禁止为省事绕过。 - 权限与敏感数据:无权限能力须隐藏或禁用(实现方式依项目);展示侧对手机、证件等 脱敏。
- 请求与输入:不信任仅前端校验;前端校验只改善体验,不作为安全边界依据。
- 依赖:禁止引入来源不明的脚本或外链处理敏感数据;依赖须可审计。
- 日志与可观测性:禁止向控制台、日志平台、错误上报 payload 输出 token、密钥、完整 Cookie、未脱敏 PII;须使用 README 约定的统一上报/日志封装(若项目尚未接入,至少集中一处可替换封装,禁止业务层散落裸
console作为唯一手段)。生产构建的 source map 策略(是否上传、是否仅内网)以 README/运维为准。 - Vue 运行时错误:渲染、
setup、组合式 API 中发生的未捕获错误,须有统一处理入口(如应用级app.config.errorHandler、布局/根组件onErrorCaptured等,具体写法以 README 与项目入口为准)。禁止仅console.error而无 用户可感知提示或与 统一上报/日志封装 的衔接,导致生产白屏或客诉无据可查;禁止在业务侧随意try/catch吞掉错误且不上报、不提示。 - 埋点 / 上报 / 监测类功能:禁止向第三方或日志系统上报 token、密钥、完整 Cookie、未脱敏 PII;事件名与 payload 宜 类型化,采集逻辑与页面展示 解耦(独立模块或 composable),避免每个按钮复制粘贴上报代码。
四、文件上传与下载(Blob)
具体大小、类型、个数、是否分片以 README 为准;本节为通用纪律。
- 下载(Blob / 文件流):禁止在未按 README/拦截器约定确认「响应为预期文件」时直接触发保存;若错误响应可能被包装为 200 + JSON/HTML,须按项目约定检查
Content-Type、魔术字节或解析探测,禁止将错误页当文件落盘且无提示。 - 上传:选择文件后、发起请求前必须校验 大小、个数、允许的 MIME/扩展名(阈值与清单以 README 为准);超限须明确提示。禁止无任何校验直接转发任意文件体。
- 大文件或长传:必须支持或与 README 一致地实现 取消(如
AbortController) 及与 组件卸载 一致的清理,避免泄漏与无效回调。
五、根目录工程基座与质量工具(通用)
以下文件通常位于仓库根目录(或 packages/<app>/ 根目录 in monorepo),与业务域无关,可在 Vue 3 + TypeScript 项目间整套拷贝再按 README 微调。具体规则条目以各文件内容为准;本节规定必须具备哪些类工具、职责分工与纪律。
1. 为何通用
- 同一套工具链保证:任意成员与 AI 产出的代码在 风格、可疑模式、类型、样式、提交说明 上与仓库一致,减少「仅本地能过、他人一拉就红」的摩擦。
- 拷贝到新项目时:优先保留 文件名与脚本约定(如
lint:eslint、lint:stylelint),替换 extends/插件版本 即可,不必重发明目录里的哲学。
2. 建议具备的根目录配置(按职责)
| 类别 | 常见文件名 | 职责(通用) |
|---|---|---|
| ESLint | .eslintrc.cjs / .eslintrc.js、eslint.config.*、.eslintignore | JS/TS/Vue 逻辑:未使用变量、any 滥用、Vue 最佳实践、与 TS 解析器配合等。 |
| Prettier | prettier.config.*、.prettierrc、.prettierignore | 格式化(引号、换行、尾逗号);与 ESLint 重复规则时须在配置中 分工(常见:eslint-config-prettier 关掉格式冲突)。 |
| Stylelint | stylelint.config.*、.stylelintignore | Vue SFC 中 <style>、SCSS/Less/CSS 的质量与约定(顺序、禁止未知 @ 规则等)。 |
| TypeScript | tsconfig.json、tsconfig.app.json 等 | 编译选项与路径别名;与 vue-tsc / Vite 共用。 |
| Vue 类型检查 | 脚本如 vue-tsc --noEmit | SFC 与类型;是否进 CI 由 README 说明。 |
| Commitlint | commitlint.config.* | 提交信息格式(常与 Conventional Commits 一致:feat:、fix: 等),便于 changelog 与 code review。 |
| Git 钩子(可选) | husky、lint-staged | 提交前对暂存区跑 eslint/prettier/stylelint,缩短反馈环。 |
| 编辑器(可选) | .editorconfig、.vscode/extensions.json / settings.json 推荐 | 缩进、换行符;推荐安装 ESLint、Prettier、Vue 等扩展,不强制提交个人 IDE 全局设置。 |
3. 与「单事实来源」的关系
- Lint/Format 的细则:以仓库内 实际配置文件 为准;本文件不逐条抄录规则 ID。Commitlint 的
type-enum、subject-*等以commitlint.config.*为准(第五节 §7 为说明与默认表)。 - README 建议补充:当前项目启用了哪些命令(如
pnpm lint:eslint)、CI 是否强制执行、Commitlint 是否与 husky 绑定。新成员与 AI 实现前可一眼看到。
4. 对开发与 AI 的纪律
- 禁止为图省事在业务代码中 大面积
eslint-disable/prettier-ignore;确需关闭须 窄范围 + 注释说明原因。 - 新增代码不得 无故抬高 既有告警级别或引入与 Prettier 冲突的手写格式(在已有
format脚本的前提下)。 - 提交信息须符合 Commitlint(若仓库已配置),格式与
type表见第五节 §7;禁止随意使用未出现在type-enum中的type(除非先改配置与团队约定)。 - 不要求每次 AI 任务末尾必须本地执行
lint(与历史约定一致);但交付的代码在风格与规则上应视为能通过当前仓库配置。
5. 新仓库最小清单(可复制检查表)
- ESLint(含 Vue + TypeScript 支持)+
.eslintignore - Prettier + 与 ESLint 不打架的集成
- Stylelint(若使用 SFC/SCSS)+
.stylelintignore -
tsconfig+ 构建/IDE 一致 - (推荐)Commitlint + Conventional Commits
- (推荐)lint-staged + husky
- README 中 一行说明:
pnpm lint:*或等价命令
6. 依赖与 lockfile(通用)
- 禁止为解决同一类问题并列引入多套职能重叠的主流基础库(如多套路由级 HTTP 封装、多套日期库),除非 README 说明迁移中或边界用途。
- 可复现安装:须将 lockfile(
pnpm-lock.yaml、package-lock.json、yarn.lock等,以项目为准)纳入版本控制;禁止在无团队约定的情况下删除 lockfile 或长期依赖未锁版本的latest/*拉取生产依赖。 - 主版本与破坏性升级:升级前须阅读 CHANGELOG / Release Notes,评估构建与运行时影响;禁止在未同步 README 或迁移说明 的情况下大范围跳主版本。
- 漏洞审计:按团队节奏执行
pnpm audit/npm audit(或 CI),对已知高危依赖按流程修复或记录经批准的例外。
7. Commitlint 与约定式提交(通用)
- 定位:与 Conventional Commits 对齐,便于 changelog、发版、Code Review 扫一眼知意图。具体校验规则以仓库根目录
commitlint.config.*(或package.json内commitlint字段)为唯一事实来源;本节为推荐形态与常见type表,若配置与本文不一致以配置为准。 - 推荐脚手架:
extends: ['@commitlint/config-conventional'],再按团队收紧或扩展rules。 - 标题格式(最常见):
<type>[(optional scope)]: <subject>- 空行后可有 body;破坏性变更可用
!置于type后,或在 footer 写BREAKING CHANGE:(与 Conventional Commits 一致,具体以所用 preset 为准)。
- 空行后可有 body;破坏性变更可用
type(须小写、非空):以下为跨项目推荐枚举(与常见config-conventional+ 团队扩展一致);若仓库删减或新增type,须同步改commitlint.config并在 README 一句说明。
type | 含义(简述) |
|---|---|
feat | 新功能 |
fix | 缺陷修复 |
docs | 文档 |
style | 纯格式(不影响代码含义) |
refactor | 重构(非 feat 非 fix) |
perf | 性能优化 |
test | 测试相关 |
chore | 构建、辅助工具、杂项 |
revert | 回滚提交 |
build | 构建系统或外部依赖 |
ci | CI 配置 |
subject(主题):禁止为空;禁止以英文句号.结尾(与常见subject-full-stop规则一致);宜 简洁、祈使语气(如「fix 登录态丢失」而非「fixed」)。主题大小写是否约束以commitlint.config中subject-case为准。- 对 AI / 开发者的纪律:生成 commit message 时须使用已配置的
type;禁止编造未出现在type-enum中的类型(如随意update、wip),除非团队已写入配置。禁止整句粘贴进subject过长无重点;较大说明放 body。 - 与 Git 钩子:若使用 husky 等在
commit-msg调用 commitlint,本地失败即修正后再提交,避免 CI 与本地不一致。
六、建议性规范(推荐,提升上限)
在已满足第一~五节前提下,用于可读性、复用性与演进成本。
1. 组合式函数(Composables)
- 导出命名
useXxx;单 composable 围绕一个清晰用例(如分页列表、表单草稿、上报通道初始化)。 - 变厚时先迁入异步与README 所载数据契约、再拆展示子组件;对外暴露 ref / computed / 方法,实现细节可隐藏。
- 返回值用普通对象便于解构;需保护的可
readonly()或仅暴露方法。 - 重复 ≥2 处的「请求 + 状态 + 错误处理」再提取,避免过早抽象。
2. 计算属性、方法与模板
- 模板保持简洁;复杂判断与数据处理进
computed或纯函数。 - 可缓存的派生状态用
computed;依赖事件入参的用方法。 - 避免深层嵌套三元,改用命名
computed或早返回函数。
3. 常量与魔法值
- 与后端或领域约定的字面量用
as const/ 枚举 / 命名常量 集中管理。 - 格式化、脱敏等与 UI 框架无关的逻辑进
utils或独立模块,便于测试。 - 除广泛约定的数字外,魔法数应有命名(如
DEBOUNCE_MS)。
4. 副作用:watch / 生命周期
- 优先
watch显式数据源;慎用无依赖清单的watchEffect。 deep: true仅在有必要时开启,并评估性能与循环触发。- 异步请求须处理 竞态(序号、
AbortController、onScopeDispose等与项目一致);禁止在组件销毁后仍写入状态。 - 多个并行请求可统一 loading,避免 UI 闪动不一致。
5. 组件契约
defineProps/defineEmits使用 TypeScript 形态,事件名与载荷类型明确。- 属性透传遵循 Vue 3
$attrs惯例,避免重复声明。
6. 注释与命名
- 注释解释 「为什么」;导出模块可简述 用途与前置条件。
- 命名用完整语义;布尔用
is/has/should;与外部 API 字段映射处可简短标注。
7. 性能(按需)
- 非首屏路由与大体积依赖:懒加载(异步组件或路由级)。
- 大列表:虚拟列表或等价方案;搜索输入 防抖/节流。
- 稳定且昂贵的子树可按文档评估
v-memo;大对象可考虑shallowRef/markRaw(明确场景)。
8. 表单与本地状态
- 校验规则宜 片段复用(常量或工厂函数),减少复制。
- 使用 localStorage / sessionStorage 等时:键名集中定义;敏感数据不落明文(与第三节一致)。
9. 横切能力(埋点、监控、配置中心)
- 采集与展示分离:上报、轮询探针、SDK 初始化等放在 独立模块 + composable,页面只调用稳定 API(如
track(event, payload)),payload 有类型定义。 - 失败可感知:上报失败宜有策略(重试队列、降级、采样),避免静默丢数且无据可查(实现深度依产品,本节为方向性要求)。
- 配置与开关:环境相关配置从 环境变量或运行时配置 注入,禁止写死环境差异大的 URL/开关。
10. 可访问性(a11y)
- 表单与可编辑控件:须有可感知的 标签关联(
label/aria-labelledby等,与所选 UI 库推荐写法一致)。 - 对话框、抽屉等浮层:打开后键盘焦点可进入浮层内控件,关闭后不将焦点留在已卸载节点(优先使用组件库内置行为;若自研须按 README 约定实现)。
- 禁止为省事移除组件库自带的 语义角色、焦点管理 等可访问性属性;关键路径应键盘可达(与 README 中 a11y 等级目标一致)。
11. 编码与可读性细节(函数、数据边界、组件)
以下提升 可读性与维护性,与第一节「硬性禁止」及第三节「异常」配合;偏 Vue / TypeScript 成熟工程习惯(含与 Vue 生态相近的写法),不绑定具体 UI 库。
- 函数参数:形参较多(约 ≥4)或含多个可选/布尔开关时,优先
options对象 +interface/type标注,避免一长串 positional 参数难以记忆与传错序。 - 布尔参数:避免
foo(a, true, false, true)无自解释性;改用 对象字段名(如{ immediate: true })或 字面量联合(如mode: 'sync' | 'async')。 - 控制流:对 null/非法输入/无权限 等先 早返回 或独立分支,再写主流程;避免四层以上嵌套
if才把「正常路径」写在最深处。 - 纯函数命名:数据整形、解析、缺省填充可用
normalize*、resolve*、ensure*、create*等前缀,使调用处一眼知「在做什么」。 - 接口数据边界:在
api返回之后、进入多个视图之前(或在专用 composable 内)将响应 规范化为内部类型/结构,减少模板与业务里重复的?.链与形状猜测(与第二节 README 契约一致)。 - 异步 UI 状态:优先
status判别联合(如'idle' | 'loading' | 'success' | 'error')或等价 有限状态,避免多个独立boolean(loading/error/empty)易不同步。 - 魔法比较:除 README 已约定的 业务码 等外,业务类型、Tab 索引等禁止裸数字/裸字符串散落;用 命名常量、
as const映射或枚举。 - 组件职责:展示以 props + emit 为主;请求、路由副作用、与后端的契约判断放在 父组件或 composable;易变或重绘频繁的区块 拆子组件 并保证 稳定
key(与第一节体量约束一致)。 - 复杂初始状态:表单/大对象初始值用
createEmptyXxx()或小工厂,避免在多个组件复制同一默认对象字面量导致引用共享 bug。 - 开发态代码:断言、冗长调试日志、仅开发可见的校验放在
import.meta.env.DEV(或 README 约定的等价开关)内,避免无分支地打进生产包体积与噪音(与第三节「日志」衔接)。 - 分支与异常:业务上「失败 / 空数据 / 取消」分支 显式命名(如
if (!ok) return+ 注释或封装handleXxxError),禁止把成功逻辑与错误处理搅在同一深层块中;catch空吞、仅console仍须遵守 第一节与第三节。
七、与项目级补充文档的关系
- 本文件为 跨项目通用下限(含目录职责与依赖方向)。
README.md(及其中链接的契约文档):API、配置前缀、文件限制、上报方式、a11y 目标、lint/CI 命令入口等的权威来源,优先于本文件对具体实现的历史记忆。- 根目录
*.config.*、.eslintrc.*、tsconfig*.json等:具体规则条目的权威来源(见第五节)。 - 各仓库项目级规则(若有):该仓库路径别名、脚手架特有目录、业务域名的权威来源,与本文「目录与模块边界」配合使用。
- 各仓库可另有 项目级规则(目录、UI 库、i18n、路由命名等)。冲突时取更严者;业务脚手架以项目文档为准。
八、后续可迭代条目(非必须)
可按需在副本中增补:provide/inject 类型策略、全局状态库边界、路由守卫与鉴权细则、E2E/单测策略;提交与分支规范若未用 Commitlint,可在 README 单独约定。