← FC Coder · HomePhase 02 · Lesson 16 · 60 min
Lesson16
Phase Two · Fantasy Builder · Matchday 16 · First Component
React 组件
给 JSX 起名字
Today's 3 Jobs · 今天这三件事
- 01新建 components/player-card/index.tsx把一坨 JSX 起名字
- 02sandbox 里 import + 用 <PlayerCard />首字母大写
- 03.map 简化 · 改组件文件看 22 张同步变改一处管一堆
Phase 1 你的 .map 里一坨 5-10 行 JSX。今天把那一坨起个名字 —— <PlayerCard />。Scratch 自定义积木 · EA FC 自定义战术 同一回事。React 组件 = 给一段 JSX 起名字。声明式 = 说要什么 · 不说怎么画。
Essence · 本质点
Declarative · 说要什么不说怎么画
教练说 4-3-3 · 球员自己跑位。React 的核心姿势。
function PlayerCard() {
return ( ...JSX... );
}
return ( ...JSX... );
}
命令式
画矩形 · 涂金 · 写字号 48 · ...
声明式
<PlayerCard />
React
用的就是声明式
你写 JSX 说「我要长这样」· React + 浏览器自己负责变成网页。Canvas 是命令式(Phase 4 见)· React 是声明式。
Essence · 改一处管一堆
组件 = UI 的 DRY
Phase 1 变量是数据的 DRY · 今天组件是 UI 的 DRY · 同一种思想。
改 PlayerCard 1 行 → 22 张卡同步变
Phase 1 #9
变量 = 数据起名字
Phase 1 #14
函数 = 步骤起名字
今天
组件 = JSX 起名字
三个本质点都是「起名字 · 改一处管一堆」。代码越大 · 这一招越重要。
Roster · 今天 3 个新工具
组件 · 声明式 · 改一处管一堆
抄着用 · 看 22 张同步变是今天的「哇」。
- 01function PlayerCard() { return ... }给一段 JSX 起名字 —— Scratch 自定义积木 · EA FC 自定义战术。首字母必须大写。export 给外面用 · import 在别处用。
- 02<PlayerCard />声明式 · 说要什么不说怎么画 —— 教练说 4-3-3 · 不说哈兰德往左 3 米。React 的核心姿势。Phase 2 第 1 个本质点。
- 03改一处 · 管一堆组件最大的力 —— 改 PlayerCard 一行 · 22 张卡同步变。Phase 1 变量是数据的 DRY · 今天组件是 UI 的 DRY。
Half 2 · 在屏幕上
抽出第一个组件 · 见证「改一处管一堆」
做完一步就点 ✓。今天的 PlayerCard 写死哈兰德,下节课 props 让它接收数据。
01新建组件文件
01Min
Cursor + pnpm dev
老三件套。
02Min
components/ 右键 New Folder · player-card
然后 player-card/ 右键 New File · index.tsx · 空白打开。
03Min
写 export function PlayerCard() { return (...哈兰德卡...) }
export function PlayerCard() { return (<article className="..."><h1>哈兰德</h1>...</article>); }。注意首字母大写。保存。
02import + 调用 · 3 张哈兰德
04Min
sandbox 里 import { PlayerCard } from '@/components/player-card'
在 sandbox 顶部 import 区。保存 · 浏览器不变(还没用)。
05Min
<main> 里手动写 <PlayerCard /> × 3
把 .map 暂时注释。换成 <PlayerCard /><PlayerCard /><PlayerCard />。保存 · 3 张哈兰德。
03.map · 改一处 22 张同步
06Min
改成 {players.map((p, i) => <PlayerCard key={i} />)}
把 3 个手动改成 .map。保存 · 22 张哈兰德(全一样 · 因为组件内写死)。
07Min
对比:今天 .map 一行 · 13 课 5-10 行
.map(p => <PlayerCard key... />) vs Phase 1 第 13 课的 .map(p => (<article ...><h1>{p.name}</h1>...</article>))。今天的简洁多了。
08Min
🌟 改 PlayerCard className 加 rotate-1 · 22 张同步变
在 player-card/index.tsx 文件里 article className 加 rotate-1。保存 · 所有 22 张卡都旋转。改一处 · 管一堆。
09Min
改回去 · 移除 rotate-1
恢复正常。
04玩 · 截图
10Min
玩 5 分钟 · 在 PlayerCard 内加 emoji 头像 · 改样式
<p className="text-5xl">⚽</p> 等等。每改一下 22 张同步变。
11Min
📸 截图战利品
Mac Shift + Cmd + 4 · 存 2026-XX-XX-我的第一个组件.png · Phase 2 第一张战利品。
Half Time · 中场 · 讲给爸爸听
4 题 · 重点:组件 / declarative / 改一处管一堆
第 2 题用「教练 vs 球员」比喻最直接。
01什么是 React 组件?用 Scratch 自定义积木的比喻讲。Hint ↓
给一段 JSX 起名字。以后用名字代替整段。Scratch 自定义积木 / EA FC 自定义战术同一回事。
02Declarative 是什么意思?用「教练 vs 球员」的比喻。Hint ↓
声明式 = 说要什么不说怎么画。教练说 4-3-3 · 球员自己跑位。
03<PlayerCard /> 首字母为什么大写?Hint ↓
React 用大写区分组件 vs HTML 标签。小写会被当 HTML。
04改一个组件文件 · 22 张卡都变 —— 这种「改一处管一堆」是什么力量?Hint ↓
复用 / DRY。Phase 1 变量是数据的 DRY · 今天组件是 UI 的 DRY · 同一种思想。
Player Rating · 本课温度计
给 Phase 2 第一节打个分
说真话。爸爸会看到。
今天难度Difficulty
0
今天开心Fun
0
Final Whistle · 终场哨
你抽出了第一个 React 组件 —— 22 张卡用一个名字管。
还有 11 步没打勾。Step 8 改组件 22 张同步变那一刻就是今天的核心 —— 其他下次补。