Skip to content

1.3 页面与组件拆解 ​

AI CODING · STAGE 1 · COMPONENT CONTRACT

先写 props、events 和页面责任,再整理 AI 任务卡。此时不创建 component、domain 或 data 文件。

时间 40–60 分钟组件 2输出 待执行任务卡
查看组件契约 →
契约先于实现
StagePicker · stages / modelValueupdate:modelValue(StageId)RecommendationCard · itemopen(recommendationId)

冻结两个组件的契约 ​

text
StagePicker
输入:stages、modelValue
输出:update:modelValue(StageId)

RecommendationCard
输入:item
输出:open(recommendationId)

StagePicker 不读取推荐数据。用户选择阶段后,它只把新的 StageId 发给父页面。

RecommendationCard 不决定 URL。用户打开卡片时,它只发出 recommendationId。同一张卡片以后放到收藏页或搜索页时,不需要改导航逻辑。

把契约写成 TypeScript 后,应接近下面这样:

ts
// StagePicker.vue
import type { Stage, StageId } from "../domain/stages";

defineProps<{
  stages: readonly Stage[];
  modelValue: StageId;
}>();

const emit = defineEmits<{
  "update:modelValue": [value: StageId];
}>();
ts
// RecommendationCard.vue
import type { Recommendation } from "../domain/recommendations";

const { item } = defineProps<{ item: Recommendation }>();
const emit = defineEmits<{ open: [id: string] }>();

这两段只冻结编译期契约,不规定 CSS、文案或 DOM 层级。AI 可以调整展示实现,不能把 StageId 降成 string,也不能把 open 改成 component 内部导航。

页面保留状态和导航 ​

首页负责三件事:

  1. 保存当前 StageId。
  2. 调用 domain 的筛选函数。
  3. 收到 open(recommendationId) 后导航到详情页。

首页不声明阶段数组,不手写筛选规则。详情页按 URL 中的 ID 调用 domain 查找函数。

1.4 创建 domain 和 data 后再接 component。现在直接让 AI 写首页,它很可能把阶段常量、筛选和导航一起塞进 component,后面的 diff 很难拆。

看见这种 Diff 就停 ​

diff
 <script setup lang="ts">
+const stages = [
+  { id: "pregnancy", name: "孕期" },
+  { id: "future-stage", name: "未约定阶段" },
+]
+const visible = computed(() =>
+  recommendations.filter((item) => item.stageIds.includes(selected.value)),
+)
+function open(id: string) {
+  uni.navigateTo({ url: `/pages/detail/index?id=${id}` })
+}
 </script>

这里同时出现了三类问题:component 新建阶段真源、component 执行筛选、component 决定 URL。不要继续补类型或兼容代码;把阶段和筛选移回 domain,把导航移回 page。

保存这张任务卡 ​

把任务卡保存到本阶段工作记录。1.4 完成 domain 和 data 后再执行。

text
Task
为阶段 1 首页拆出阶段选择和推荐卡片两个组件。

Allowed files
- 创建 apps/web/src/components/StagePicker.vue
- 创建 apps/web/src/components/RecommendationCard.vue
- 修改 apps/web/src/pages/index/index.vue

Do not modify
- apps/web/src/domain/stages.ts
- apps/web/src/domain/recommendations.ts
- apps/web/src/data/recommendations.ts
- package.json、lockfile、build config
- 任何 Mock 数据结构

Contract
- StagePicker 接收 stages、modelValue
- StagePicker 发出 update:modelValue(StageId)
- RecommendationCard 接收 item
- RecommendationCard 发出 open(recommendationId)
- 首页负责状态、筛选和导航

Validation
- npm run test:web,预期 11 passed
- npm run build:web,预期 exit 0
- H5 四条路径由工程师人工检查

Return
- 修改文件清单
- test 与 build 的实际输出
- diff 摘要
- 未执行的人工检查

先复述 allowed files、do not modify、props/events 和 validation。
我确认后再修改。

AI 复述时,允许范围应正好是两个 component 和首页。它若要求同时修改 domain 或 data,任务还没有拆干净。

详情页单独发一张卡 ​

text
Task
补齐阶段 1 推荐详情页。

Allowed files
- 创建 apps/web/src/pages/detail/index.vue
- 修改 apps/web/src/pages.json

Do not modify
- apps/web/src/domain/
- apps/web/src/data/
- apps/web/src/components/
- package.json、lockfile、build config

Query contract
- 从 onLoad(query) 读取 query.id
- query.id 不是 string 时按空 ID 处理
- 使用 findRecommendation(RECOMMENDATIONS, id)
- 不在页面复制 Mock 数据

Behavior
- 合法 ID 显示标题、摘要、推荐依据和注意事项
- 非法 ID 显示“没有找到这条推荐”

Validation
- npm run build:web,预期 exit 0
- npm run dev:web 后人工检查“南瓜泥入门”和不存在 ID

Return
- 修改文件
- build 的实际输出
- diff 摘要
- 未执行的人工检查

先复述 allowed files、do not modify、query contract 和 validation。
确认后再修改。

component task 与 detail task 分开执行。第一组出错时只检查 component 和首页;第二组出错时只检查 route registration、query 和 detail lookup。

执行任务时看 Diff ​

1.4 运行任务卡后,直接打开这三个文件的 diff:

bash
git diff -- apps/web/src/components/StagePicker.vue \
  apps/web/src/components/RecommendationCard.vue \
  apps/web/src/pages/index/index.vue

按顺序检查:

  • StagePicker.vue 是否只接收 stages、modelValue。
  • RecommendationCard.vue 是否只接收 item。
  • events 是否分别为 update:modelValue 和 open。
  • 首页是否接收 events,并调用 domain 完成筛选与导航。
  • 三个文件里是否复制了阶段 ID、阶段数组或推荐规则。

npm run test:web 只覆盖 domain 回归,npm run build:web 只说明可以编译。component event、route param 和页面查询要靠四条 H5 路径确认。

实现结果不符合契约时
现象处理
AI 修改了 domain 或 data从当前任务移出这些改动,回到 allowed files
props / events 类型不匹配对照固定契约修 component;不要在页面加兼容分支
列表或导航不对查首页是否接收 event 并调用既定 domain 函数
component 出现阶段数组删除重复常量,继续从 domain/stages.ts 引用

任务卡和 Review 清单准备好后,进入 1.4 用 Mock 数据跑通首屏。

晨悦 AI 实践手册