← FC Coder · HomePhase 01 · Lesson 12 · 60 min
Lesson12
Phase One · First App · Matchday 12 · One Line · Ten Cards

一行渲染
10 张卡

Today's 3 Jobs · 今天这三件事
  1. 01
    扩 roster 到 10 人 · 删掉手动 3 张卡
    为 .map 腾位置
  2. 02
    🌟 {roster.map(name => <article>{name}</article>)}
    Phase 1 第一个「哇」
  3. 03
    加 className 让 10 张卡都有曼城蓝
    多行 JSX 用 () 包

上节课你手动写 3 个 article 渲染 3 个名字。今天 `.map` 进场 —— 一行代码,数组多长就出多少张卡。这是 Phase 1 第一个「哇」 —— Phase 0 的 `.forEach` 是兄弟(不收东西),今天的 `.map` 是会收一堆的版本。

Essence · 本质点

循环 = 对每一个做同样的事

Phase 0 第 4 课见过 .forEach;今天的 .map 是会收东西的版本。

Chalk Board · 兄弟俩
{roster.map(name => (
<article>{name}</article>
))}
一行 · 数组多长出多少
Phase 0 第 4 课
cards.forEach(c => c.style...)
今天
roster.map(name => <Card .../>)
.forEach 不收 / .map 收一堆

JSX 里要「收一堆 JSX 卡」—— 只能用 .map。这就是为什么 React 里 .map 比 .forEach 常见 10 倍。

Essence · 多行 JSX 用 () 包

单行不用 · 多行必用

告诉浏览器「整一坨都是返回值」。

Chalk Board · 单行 vs 多行
name => (
<article className="...">
<h1>{name}</h1>
</article>
)
单行 · 不用 ()
name => <p>{name}</p>
多行 · 必用 ()
name => ( <article>...多行...</article> )
不用 ()
返回 undefined · JSX 渲染空
Roster · 今天 3 个新工具

.map · 临时变量 · () 包多行

抄着用 · 改一改数组看变化 · 5 分钟就熟。

  1. 01
    arr.map(item => <X>{item}</X>)
    对每一个,返回一个新东西 —— Phase 0 .forEach 的小哥哥(会返回的版本)。
    JSX 里渲染列表的唯一姿势。返回一个新数组 · JSX 自动铺开。
  2. 02
    name / player / x
    临时变量名 · 你起的 —— 数组每个元素的"临时绰号"。
    JSX 里跟着用同名就行 · 改一个改全部。
  3. 03
    name => (<article>多行</article>)
    多行 JSX 用 () 包 —— 单行不用 · 多行必用。
    告诉浏览器「整一坨都是返回值」。
Half 2 · 在屏幕上

回 sandbox · 一行 .map · 10 张卡出现

做完一步就点 ✓。Step 4 那一下就是今天的「哇」。

01扩 roster · 清掉手动 3 张
01Min

Cursor + pnpm dev + 打开 sandbox

回 07-my-first-card/sandbox。上节课你写了 3 个手动 article。
02Min

扩 roster 到 10 人(可分多行写)

['哈兰德','福登','罗德里','德布劳内','阿坎吉','埃德森','多库','贝尔纳多','阿克','冈萨雷斯'];保存。还是 3 张卡(因为还是手动)。
03Min

删掉 3 个手动 <article>

<main> 里只留 <p>我们队有 {roster.length} 个球员</p>。其他全删。保存 · 卡都没了。
02🌟 一行 .map · 10 张卡出来
04Min

🌟 </p> 下面加 {roster.map(name => <article>{name}</article>)}

保存 · 10 张卡(裸 article,无样式 · 一行一个名字)自动出现。Phase 1 第一个「哇」。
05Min

加 '格瓦迪奥尔' 到 roster 末尾

保存 · 第 11 张卡自动出现 · 上面计数也变 11。数据加一个 · UI 加一张 —— 这就是 .map 的真本事。
06Min

看 DevTools Console · ⚠️ key 警告

弹「Each child in a list should have a unique key prop」。今天故意不管 · 下节课对象进场时引入 key。痛点 → 解法,印象深 10 倍。
03给 .map 的 article 上 className
07Min

改成多行 · 用 () 包

{roster.map(name => (\n <article className="bg-sky-600 text-slate-50 p-6 rounded-lg mb-4">\n <h1 className="text-amber-500 text-3xl">{name}</h1>\n <p>ST · 9 号</p>\n </article>\n))}\n保存 · 10 张曼城蓝卡。
08Min

改 name → player (改临时变量名)

.map(player => ... {player} ...) · 保存 · 浏览器一样。变量名是你起的 · 改一处改全部。
09Min

发现 · 所有卡都是 ST · 9 号 假数据

现实里罗德里是 CM · 埃德森是 GK。今天不解决 · 下节课对象进场 · 每球员各自的 position。
04玩 · 加人减人 · 截图
10Min

玩 5 分钟 · 各种数组

改顺序 / 删人 / 加人 / 试 (name, index) => <p>{index + 1}. {name}</p> · 看序号自动跟着出来。
11Min

📸 截图战利品

Mac Shift + Cmd + 4 框选 10 张并排卡 · 存 2026-XX-XX-我的10张卡.png · Phase 1 第七张战利品。
Half Time · 中场 · 讲给爸爸听

4 题 · 重点:.map = 对每一个收一堆

第 3 题让他感受 .map 的真本事。

01什么是 .map?用「首发训练」的比喻讲。Hint ↓

对每一个球员收一张报告(返回一堆新东西)。.forEach 是做深蹲不收,.map 是收。

02.map 和 .forEach 差在哪?为什么 JSX 里只能用 .map?Hint ↓

.forEach 不返回,.map 返回新数组。JSX 要「收一堆 JSX」 —— 只能 .map。

03加一个名字到 roster · 浏览器自动出新卡。如果用上节课的手动写法,你要做什么?Hint ↓

手动复制一个 <article> 写 roster[10]。.map 自动 · 数据加一个 UI 加一张。

04Console 弹的黄色警告是什么?为什么今天不管?Hint ↓

key prop 缺失。下节课对象进场,每张卡有 name 当身份签,自然给 key={player.name}。

Player Rating · 本课温度计

给 Phase 1 第一个「哇」打个分

说真话。爸爸会看到。

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

你写了一行 · 浏览器出 10 张卡。你已经是真程序员。

还有 11 步没打勾。Step 4 看到 10 张卡那一刻已经命中今天的核心 —— 其他可以下次补。