前端开发规约(TypeScript + Vue 3)
以 docs/前端开发手册-TypeScript-Vue.md 为唯一规则源。目标是产出能过评审的代码,不是复述规范条文。
何时用
- 新写 / 改造页面、业务组件、公共组件、组合式函数
- 设计 API 层、类型定义、Pinia store、路由与权限
- 处理请求异常、错误码映射、日志与埋点
- 按手册评审前端代码,输出带定位与修法的违规清单
- 排查"点了没反应""数据串台""页面白屏""内存泄漏"
- 接手既有工程 / JS→TS 迁移 / 给若依类后台加固类型
0. 接手既有工程:先验类型门禁
不要先读业务代码。 先确认"类型错误会不会被拦住",三条命令定生死:
grep -rn "declare module" src --include=*.d.ts # 有无空模块声明遮蔽 axios/element-plus/*.vue
grep -n "vue-tsc\|type-check" package.json # 构建是否跑类型检查
grep -nE "noUnusedLocals|noImplicitReturns" tsconfig.json
一行搞定(P 系列 = 工程配置,C 系列 = 循环依赖):
python scripts/check_frontend.py . --only P001,P002,P003,P004,P005,C001
任一条不合格,就按 references/06 的 §1→§2 修门禁,再跑 npm run type-check 拿到真实错误清单——那份清单才是工作量。门禁没修就改业务代码,等于在没有刻度的尺子上量长度。
判定口诀:strict 开着 + 构建不跑 vue-tsc + declare module 'axios' = 没有类型。
工作流
- 判定任务类型,只加载需要的参考文件:
| 任务 | 加载 |
|---|---|
| 写组件 / 组合式函数 / 类型 | references/01-编程规约速查.md |
| 接口封装、错误码、异常、日志埋点 | references/02-接口契约与异常日志.md |
| 状态管理、目录分层、构建依赖 | references/03-状态与工程结构.md |
| 单测、安全、组件设计 | references/04-测试安全与设计.md |
| Code Review / 提测自检 | references/05-评审清单.md |
| 若依/RuoYi 类后台、Element Plus、JS→TS 迁移、类型门禁加固 | references/06-若依工程范式与TS加固.md |
| 多包/monorepo、分层与包边界、门禁与 CI、循环依赖、规模化协作 | references/07-工程化与规模化约定.md |
-
动手前先定契约(与后端对齐,不确定就问):接口路径与方法、字段命名 lowerCamelCase、空值语义(列表空返回
[])、大整数用 string、金额单位(分)、时间格式(yyyy-MM-dd HH:mm:ss)、错误码与用户提示、分页参数(pageNum从 1 开始)。 -
按单向依赖落位:
views(取数+编排) → components(只吃 props) → composables(可复用逻辑) → api(只发请求) → utils(纯函数)。禁止 components 直连 api、utils 依赖 store。 -
落三条主流程:数据流(props 下行 / emit 上行 / store 管共享)、异常流(请求层转
ApiError→ 全局兜底 → 局部onErrorCaptured→ 三态 UI)、权限流(路由守卫 + 按钮级指令,均只作体验优化,真正鉴权在后端)。 -
跑自检脚本(推荐):
python scripts/check_frontend.py <目录或文件> --format text
python scripts/check_frontend.py <目录或文件> --only R001,R003,P001 # 只看类型门禁
三个规则族:
- F 系列:
any、v-html、index当 key、v-if+v-for同用、props 赋值、深 watch、localStorage存 token、console.log、JSON.parse(JSON.stringify())、target="_blank"无 rel、moment、裸 axios 等; - R 系列(类型逃逸):空
declare module遮蔽第三方类型、*.vueshim、proxy: any、TS 组件用运行时defineProps、Promise.reject('字符串')、{} as T、TableDataInfo<T[]>泛型套错、meta as any、包深路径引用、new Promise包已有 Promise; - C 系列(循环依赖):本地 import 图 + 逐文件 tsconfig 别名解析,输出完整环链,区分桶文件互引与自引用导入,忽略
import type; - P 系列(工程门禁,传目录时自动触发):
package.json无type-check、tsconfig缺严格开关、allowJs: true、无 ESLint、多包工程无循环依赖门禁。
命中需人工确认。脚本通过 ≠ 类型安全,它替代不了 vue-tsc 与 lint。目录模式下 C001 需要遍历全量文件,大仓约 5–10 秒,可用 --no-circular 跳过。
- 交付时给出:改了哪些文件、遵循/违反了哪条规约、三态与异常处理是否闭环、已知风险。评审输出按「级别 / 位置 / 违反条目 / 修法」四列。
不能破的底线
- 禁用
any(用unknown+ 收窄);API 请求与响应必须有显式类型。 v-for的:key必须是业务唯一 ID,永不用index。- 禁止在子组件改 props;双向绑定用
defineModel/update:modelValue。 v-if与v-for不同元素同用(先computed过滤)。- 所有 Promise 有 catch;无依赖请求并行(
Promise.all),切换场景取消在途请求(AbortController)。 - 提交类操作防重复:按钮 loading + 幂等键;金额用"分"整数计算。
- 大整数(订单号/雪花 ID)按 string 处理,禁止
Number()。 - 用户可控内容禁止
v-html(必须 DOMPurify);token 不放localStorage;外链加rel="noopener noreferrer"。 - 页面必须有加载态 / 空态 / 错误态,缺一视为未完成。
- 定时器、事件监听、WebSocket、Observer 必须在
onUnmounted清理。 - 不许让检查器闭嘴:禁空
declare module、禁*.vueshim、禁proxy: any、禁无理由@ts-ignore;TS 工程必须有vue-tsc --noEmit门禁。 - 不许留环:本地模块之间禁止循环依赖(含桶文件互引);跨包只从包入口导入,禁止
@scope/pkg/src/...深路径。
反模式(见到就亮红灯)
- 组件里直接
axios.get('/api/...'),绕过统一请求层 catch (e) { console.log(e) }后用户看不到任何提示watch(obj, fn, { deep: true })监听整个大对象- 一个 SFC 800 行,template 里塞满表达式和
v-if分支 - store 里既取数又存 UI 状态又做路由跳转
- 用
sessionStorage传对象做页面间通信 setTimeout里改状态却没在卸载时清理- 表格前端全量拉取再本地分页(十万条)
declare module 'axios'/declare module '*.vue'/proxy: any—— 三条让strict归零的写法lang="ts"里还在用运行时defineProps({...}),等于给 props 贴了个anyPromise.reject('字符串'),catch 端e.message恒为undefined- 拦截器错误分支写了
Promise.reject(error)却忘了return(错误被吞成undefined) - API 层手写
Promise<TableDataInfo<T[]>>,声明与实现各说各话 new Promise((resolve) => { api().then(...) })给已有 Promise 再包一层- 桶文件
index.ts与它的成员互相 import(barrel 环,见C001) import { x } from '@scope/ui/src/button'绕过包 exports 契约- 每个页面各写一遍
roles.includes(...)判权限,而不是走统一的useAccess
参考文件索引
references/01-编程规约速查.md— 命名、常量、格式、TS 类型与类型逃逸、Vue 组件、日期、数组、异步、控制、注释、前后端、其他references/02-接口契约与异常日志.md— 请求层、ApiError、错误码映射、全局兜底、日志埋点references/03-状态与工程结构.md— Pinia、缓存、目录分层、依赖与构建references/04-测试安全与设计.md— Vitest、安全、组件设计与可访问性references/05-评审清单.md— 提交前逐项勾选(含类型门禁 P0 组)references/06-若依工程范式与TS加固.md— 若依/RuoYi 骨架的类型化写法、迁移顺序、修复配方references/07-工程化与规模化约定.md— 四层分层与依赖方向、包导出契约、别名三处同步、tsconfig 分档、请求层可配置契约、路由 meta 增强、权限三形态、门禁脚本化、测试与构建策略
来源与授权
- 手册与规则:本技能的《前端开发手册(TypeScript + Vue)》为自撰,体例参照阿里巴巴《Java 开发手册(嵩山版)》的「维度 + 三级约束 + 说明/正例/反例」结构,不含其条文原文。
- 参考工程:RuoYi-Vue3(MIT)、vue-vben-admin(MIT)的范式提炼,仅描述通用做法,不复制其源码。
- 技能结构、工作流、自检脚本:MIT。
- 源仓库:
https://gitee.com/littlelichunhang-astronaut/file-material