一个实战示例:"收藏"功能
我们来端到端地做一个小功能:用户可以把列表里的条目标记为收藏,并看到自己收藏了多少个的计数。
切分它
我会这样把它拆成纵向步骤:
- 在每个条目旁边加一个星标按钮(暂时什么都不做,只是显示出来)。
- 点击星标切换它的亮/灭外观(仅状态,不保存)。
- 显示一个反映这些切换的"★ 3 favorites"计数器。
- 保存收藏,让它在页面重新加载后依然存在。
注意每一步都可独立运行、可见。你在其中任何一步之后停下,都仍然拥有一个可运行的应用。
第 1 步:按钮
一条好的提示会点明文件、改动,以及不要碰什么:
在 ItemCard 组件(src/components/ItemCard.jsx)中,给每张卡片的
右上角加一个星标按钮。它应该渲染一个轮廓星标图标。先别接上任何
点击行为——只让它显示出来。保持卡片其余的布局不变。
运行应用。看到星标了吗?好。提交:
git add -A && git commit -m "Add star button to item cards"
第 2 步:切换状态
让星标按钮在被点击时在填充和轮廓之间切换。用本地组件状态来追踪
它——先别保存到任何地方。填充的星标表示已收藏。
可以把状态(state)想成应用的短期记忆——此刻什么是真的,比如某颗星星现在是否处于填充状态。现在你在同时处理状态和 UI,这很正常。(UI,即用户界面,就是应用中人能看到、能点击的那一部分。)AI 大概会加上类似这样的东西:
const [isFavorite, setIsFavorite] = useState(false);
<button onClick={() => setIsFavorite(!isFavorite)}>
{isFavorite ? <StarFilled /> : <StarOutline />}
</button>
点几下星标。它们会切换吗?提交。
第 3 步:计数器
在条目列表顶部加一个"★ N favorites"计数器。它应该统计当前有多少
个条目的星标被填充。如果需要,把收藏状态上提到列表组件,好让
计数器能看到它。
这一步可能要求 AI 重构状态所在之处——这在预料之中,而这恰恰是为什么你要把它作为独立的小步骤来做。运行它,切换几个星标,看着数字变化。提交。
第 4 步:让它持久化
把收藏持久化,让它们能挺过页面重载。现在先用 localStorage——每当
收藏条目 ID 的列表变化时就保存它,并在启动时加载它。
(localStorage 就是浏览器在访客自己电脑上保留的一个小记事本,应用可以把东西记下来,重新加载之后再找回来。)重新加载页面。还是收藏状态吗?你刚刚交付了一个功能,一次一个可运行的切片。
来看看这个完成的功能里各部件是怎么互相对话的。一次点击向下流入状态,屏幕从状态重绘,而状态被镜像到存储里,于是它在重新加载后依然存活:
┌─────────────────────────────────────────────┐
│ │
点击星标 从状态
│ (事件) 重绘
▼ ▲
┌────────┐ 更新 ┌─────────┐ 馈送 ┌────────┐
│ UI │─────────────▶│ 状态 │───────────▶│ UI │
│ (按钮) │ │(应用内 │ │(填充的 │
└────────┘ │ 内存) │ │ 星标 + │
└────┬────┘ │计数器) │
│ 变更时保存 └────────┘
▼
┌──────────┐
│ 存储 │ ◀── 启动时加载,
│(localSt.)│ 所以它能挺过重载
└──────────┘