← FC Coder · HomePhase 01 · Lesson 13 · 60 min
Lesson13
Phase One · First App · Matchday 13 · Full Dossier

一张卡的全部信息
对象

Today's 3 Jobs · 今天这三件事
  1. 01
    把数组从字串升级成对象 · 5 个属性
    {name, rating, position, nationality, club}
  2. 02
    .map 里用 player.name / player.rating 渲染
    对象用名字 · 数组用索引
  3. 03
    加 key={player.name} · 还 12 课的债
    Console 黄色警告消失

上节课 .map 让 10 张卡出来,但全是 ST 假数据 —— 因为每个球员只是一个名字。今天每个球员变成一份档案 —— `{name, rating, position, nationality, club}` 5 个属性。对象 = 一堆带名字的属性打包。顺便还上节课的 key 债。

Essence · 本质点

对象 = 一堆带名字的属性打包

数组横着看,对象纵着看。两者结合(数组装对象)是真实数据的形状。

Chalk Board · 数组 vs 对象
const roster = [
{ name: '哈兰德', rating: 91, position: 'ST', ... },
{ name: '福登', rating: 87, position: 'LW', ... },
];

roster[0].name → '哈兰德'
数组
['a', 'b', 'c'] · 用 [0]
对象
{n: '哈', r: 91} · 用 .n
组合
[{...}, {...}]

EA FC 数据库就是这个形状 —— 一个数组 · 装一堆对象 · 每个对象一份档案。Phase 1 后半 + Phase 2-5 全程的真实数据形状。

Essence · key prop

每张卡的唯一身份签

React 内部要 key 才能高效更新 —— 上节课弹的警告今天解决。

Chalk Board · key 的意义
<article key={player.name} className="...">
没 key
Console ⚠️ Warning · React 困惑
有 key
React 认识每张卡 · 高效更新
今天用
key={player.name}

key 必须唯一。今天用 name(没重名)。Phase 3 数据库进场,id 字段成为更稳的 key。

Roster · 今天 3 个新工具

对象字面量 · .访问 · key prop

抄着用 · 改一改属性看变化 · 综合到一张卡。

  1. 01
    { name: '哈兰德', rating: 91 }
    对象字面量 —— 花括号 + 「key: value」对子 · 逗号分。
    key 不用引号 · value 字用 ' · 数字不用。
  2. 02
    player.name / player.rating
    属性访问 —— . 接属性名。对象用名字找 · 数组用索引找。
    拼错属性 → undefined · 卡上空白 · JSX 不报错。
  3. 03
    <article key={player.name}>
    唯一身份签 —— React 内部要知道哪张卡是哪张才能高效更新。
    今天用 player.name · Phase 3 数据库用 player.id。
Half 2 · 在屏幕上

升级你的 roster · 用真实数据

做完一步就点 ✓。综合 .map + if 是今天的压轴。

01数组升级 · 字串 → 对象
01Min

Cursor + pnpm dev + 打开 sandbox

回 07-my-first-card/sandbox。看 12 课的 10 张全是 ST 假数据卡。
02Min

roster 升级 · 10 个对象

每个元素从 '哈兰德' 变成 { name, rating, position, nationality, club } 5 属性。10 个对象保存。卡的标题变 [object Object] · 正常 · 因为 JSX 不知道显示哪个属性。
02🌟 .map + .name + .rating + ...
03Min

.map 里 {player} → {player.name}

<h1>{player.name}</h1>。保存 · 名字回来了。还是 ST 9 号假数据(下一步换真的)。
04Min

🌟 显示真实位置 + 评分

<p>{player.position} · 评分 {player.rating}</p>。保存 · 哈兰德ST91 · 福登LW87 · 罗德里CM90 ... 每张卡都对得上。
05Min

再加一行 · 国家 + 俱乐部

<p className="text-sm text-slate-200">{player.nationality} · {player.club}</p>。10 张卡 5 项完整信息全显示。
03加 key · 还上节课的债
06Min

🌟 还 key 的债 · key={player.name}

<article key={player.name} className="...">。保存 · 打开 DevTools Console · 黄色警告消失。
04综合 · if 判断每张卡 · 截图
07Min

.map + if 综合 · 每张卡独立判断金边

.map(player => { let borderClass = '...'; if (player.rating >= 90) { borderClass = '金边'; } return (<article ...>...</article>); }) · 注意大括号 + return。保存 · 哈兰德 + 罗德里 (91/90) 有金边 · 其他没。
08Min

改哈兰德 rating: 85 · 金边消失

降到 85 · 保存 · 他的金边消失。恢复 91 看金边回来。.map 里每张卡独立判断 · 互不影响。
09Min

玩 5 分钟 · 改属性看变化

改一个 player 的 position / nationality / club · 看那张卡变。加第 11 个球员 · 自动出第 11 张。
10Min

📸 截图战利品

Mac Shift + Cmd + 4 框选 10 张完整阵容。存 2026-XX-XX-我的10人完整阵容.png · Phase 1 第八张战利品。
Half Time · 中场 · 讲给爸爸听

4 题 · 重点:数组 vs 对象 · key 的为什么

第 2 题让他用「横看 / 纵看」的比喻讲。

01什么是对象?用「球员档案」的比喻讲。Hint ↓

一堆带名字的属性打包。5 个标签 + 值的对子 = 一张档案。

02数组和对象差在哪?Hint ↓

数组横着看(一串同类)· 对象纵着看(一堆属性)。数组用索引,对象用名字。

03player.name 读出来是?为什么不是 player[name]?Hint ↓

player 对象的 name 属性。. 比 [] 直觉 · [] 是动态访问,今天不教。

04key={player.name} 解决了上节课什么问题?为什么 React 要 key?Hint ↓

每张卡的唯一身份签 · React 内部高效更新。上节课 Console 黄色警告今天消失。

Player Rating · 本课温度计

给「真实数据上线」打个分

说真话。爸爸会看到。

今天难度Difficulty
0
今天开心Fun
0
Final Whistle · 终场哨

你的 10 人完整阵容上线了 —— 真实数据 · 自动金边 · 唯一 key。

还有 10 步没打勾。Step 4 真实评分 + Step 7 综合金边 · 都命中今天的核心。其他可以下次补。