| name | refactoring-reference |
| description | 本项目编码规范与重构指南。指导 AI 在写代码/改代码时主动避免坏味道,写出符合项目标准的高质量代码。
MUST USE when 写新代码、修改现有代码、code review、用户提到重构/坏味道/code smell/代码质量/命名/长函数/重复代码。
每次改动代码后应自查:是否引入了新的坏味道?
|
本项目编码与重构规范
核心理念
写代码时就用正确的方式写,而不是等坏了再修。
项目技术栈
- Vue 3 Composition API +
<script setup> + TypeScript
- Vite 8 + pnpm
- 代码组织:composables(逻辑)、utils(纯函数)、components(视图)
写代码时必须遵守的规则
1. 单一职责
一个函数/组件只做一件事。
// ❌ 函数名 buildXxx 内部还修改了全局状态(副作用)
export function buildWalkConfig(cw: number) {
walkLabels.value = labels // 副作用!调用者不知道
return { ... }
}
// ✅ 纯函数只返回数据,副作用留给调用者
// 如果需要同时更新全局状态,在调用处做
const config = buildWalkConfig(cw)
walkLabels.value = config.labels
2. 不要硬编码——用命名常量
// ❌
setTimeout(() => walkToCenter(cw), 300)
devW.value = Math.min(900, Math.max(640, ...))
// ✅
const WALK_CENTER_DELAY = 300
const DEV_MIN_W = 640, DEV_MAX_W = 900
setTimeout(() => walkToCenter(cw), WALK_CENTER_DELAY)
devW.value = Math.min(DEV_MAX_W, Math.max(DEV_MIN_W, ...))
3. 全局状态用响应式而非轮询
// ❌ 非响应式全局 + 定时器轮询
;(window as any).__walkLabels = labels
setInterval(() => syncFromGlobal(), 500)
// ✅ Vue 响应式 ref
export const walkLabels = ref<string[]>([])
watch(walkLabels, (labels) => { ... })
4. 重复两次就提炼
同一个逻辑出现在两个地方 → 抽到 utils 或 composable。
// ❌ DemoBar 和 OpPanel 各写一遍 walk presets 生成逻辑
// ✅ 抽到 walk.ts: buildWalkPresets(),两处 import 使用
5. 优先用 composable 拆分大组件
组件超过 300 行 → 考虑抽取 composable。
// ❌ App.vue 463 行,混入 layout/buildConfig/theme/全屏逻辑
// ✅ 抽 useLayout.ts、useFullscreen.ts,App.vue 降到 < 350 行
6. 响应式数据用 Vue API,别挂在 window 上
// ❌
;(window as any).__xmovSdk = sdk
;(window as any).__youlingUi = { ... }
// ✅ 对于确实需要跨组件共享的数据,用 provide/inject 或独立 ref
// 对于 SDK 实例这类第三方对象,window 可作为妥协方案但应加注释说明原因
7. 文本显示避免空值陷阱
// ❌ .toFixed(0) 返回 "0"(truthy),|| '--' 永远不触发
{{ value.toFixed(0) || '--' }}
// ✅
{{ value > 0 ? value.toFixed(0) : '--' }}
常见坏味道 → 本项目修复手法
| 坏味道 | 本项目手法 | 示例 |
|---|
| 重复代码 | 抽到 src/utils/xxx.ts | makeWalkSsml、walkLabel |
| 上帝组件 | 抽 composable (useXxx) | useLayout、useAppConfig |
| 全局可变状态 | 改用 Vue ref + watch | walkLabels |
| 定时器轮询 | 改用响应式 watch | DemoBar syncWalkPresets |
| 魔法数字 | 命名常量 | WALK_MARGIN、REINIT_DELAY |
| 长函数 (>40行) | 提炼函数 | generateConfig 可拆 |
| 副作用隐藏 | 函数名体现副作用 或 移到调用处 | buildWalkConfig |
| 神秘命名 | 改名表达意图 | fn → calculatePriceWithTax |
文件组织约定
src/
components/ # Vue 组件,每个文件 < 300 行
composables/ # Vue composable(带响应式状态)
utils/ # 纯函数工具(无副作用)
config/ # 静态配置常量
types/ # TypeScript 类型定义
utils/*.ts → 纯函数,可被任意文件 import
composables/*.ts → Vue composable,返回 ref/reactive/computed
components/*.vue → 视图组件,逻辑尽量薄
Code Review 检查清单
每次改动代码后自查:
□ 有没有引入新的重复代码?(同一逻辑出现两次?)
□ 函数是否超过 30 行?(考虑提炼)
□ 有没有新的魔法数字?(命名常量替代)
□ 有没有 setInterval 轮询?(改用 watch)
□ 有没有 console.log 遗留?
□ 有没有副作用隐藏在纯函数里?
□ window 上有没有新增全局变量?
□ .toFixed() 后面有没有 || '--' 陷阱?
□ TypeScript 类型检查是否通过?
坏味道完整目录
详见 REFERENCE.md,涵盖 22+ 种坏味道和 60+ 种修复手法。