LESSON 4.3 / MODERN FRONTEND

React:用组件组织界面

框架不是魔法,而是一套组织规则。React 让界面围绕组件组织,并通过 props 组合和复用。

预计阅读15–20 分钟
完成结果能读懂组件树,并知道数据是如何向下传递的。
本课目标
  • 能读懂组件树,并知道数据是如何向下传递的。
  • 原生 Web、框架和构建工具的关系
  • 把静态页面重构为导航、标题、卡片列表和卡片四类组件。
开始之前
  • 完成 4.2「Node.js、npm 与构建工具」
01

FOUNDATION

必须理解

框架不是魔法,而是一套组织规则。React 让界面围绕组件组织,并通过 props 组合和复用。

React 用组件描述界面应该怎样随数据变化。它减少手动寻找和修改 DOM 的代码,让页面由可组合的函数与明确输入构成。

先建立整体直觉

组件像积木模具:TaskItem 定义一条任务长什么样,传入不同 props 就得到不同内容;多个 TaskItem 组合成列表,再组合成页面。

贯穿本课的实际场景

任务应用拆为 TaskForm、TaskList、TaskItem 和 FilterBar;页面组件保存任务数据并把需要的信息传给子组件。

概念 1

原生 Web、框架和构建工具的关系

先用白话理解

React 组件通常就是一个返回界面描述的 JavaScript 函数,名字要用大写开头。JSX 看起来像 HTML,其实是让你能在 JavaScript 里更直观地描述页面。

基础概念

原生 Web 平台提供 HTML、CSS、JavaScript 和浏览器 API;React 是用于声明用户界面的库;构建工具负责转换模块、JSX 与资源并提供开发体验。

进一步理解

React 不替代浏览器,最终仍生成浏览器能处理的 DOM。它主要改变组织界面和状态更新的方式:开发者描述某个数据状态下界面应是什么。

构建工具也不是 React 本身。简单 React 可以通过其他方式运行,但真实项目通常需要模块解析、TypeScript、开发服务器和生产优化。

放进实际场景

任务列表仍由 button、ul 等原生元素组成,React 负责根据任务数组组合它们,构建工具把 TSX 转换并打包给浏览器。

容易混淆的地方

“框架”常被宽泛使用,但准确理解职责更重要:React 管 UI 模型,Next.js 再补路由与服务端能力,构建器处理工程转换。

这一小节记住:先分清平台、界面库和构建环境,错误才不会全部归咎于 React。

概念 2

组件、JSX、props 与组合

先用白话理解

props 是父组件交给子组件的输入,子组件应该把它当成只读数据。用户点了什么,可以通过回调告诉父组件,由真正拥有数据的地方决定怎么改。

基础概念

组件是可组合的界面单元,通常用函数根据输入返回界面描述;JSX 是在 JavaScript 中描述元素树的语法;props 是父组件传入的只读数据。

进一步理解

组件名称用大写开头,让 React 区分自定义组件与原生标签。父组件通过 props 传值和回调,子组件读取它们来显示或通知事件,不应直接修改 props。

组合允许父组件把内容嵌入子组件,也允许同一组件使用不同数据重复渲染。组件每次计算应尽量保持纯粹,相同输入得到相同界面。

放进实际场景

TaskList 把每条任务作为 props 交给 TaskItem;TaskItem 显示标题和完成状态,并通过 onToggle 通知上层用户点击。

容易混淆的地方

props 与 state 不同:props 由外部传入,state 是组件需要记住并可更新的信息;两者都能影响渲染。

这一小节记住:组件通过 props 接收事实,通过组合形成页面,通过回调报告事件。

概念 3

按业务单元拆分,而不是拆得越细越好

先用白话理解

一张任务卡、一个任务列表、一个新增表单都算清楚的业务单元,适合做组件。但如果只是包了一层文字,又没有独立职责,就没必要单独建文件。

基础概念

组件边界应围绕独立职责、可重复结构或独立变化原因划分。拆分目标是降低理解成本,而不是让文件数量最大化。

进一步理解

一个组件最好能用一句话说明职责,并拥有清楚输入与输出。任务卡、筛选栏和新增表单往往有独立语义;只有一层样式包装的 span 通常不值得单独抽象。

过大的组件会混合数据、交互和多个页面区域;过小的组件则迫使读者频繁跳转。可以先写清楚,再在重复或变化边界出现时重构。

放进实际场景

新增任务表单自己管理未提交输入并通过 onCreate 交出标题;列表只负责展示和空状态,页面负责协调数据。

容易混淆的地方

视觉区域不必一一对应组件。两个看起来分开的块若始终共享同一职责,可能应留在一起;同一区域也可能包含多个业务单元。

这一小节记住:好的组件边界让数据方向和修改位置更容易预测。

一个有明确输入的组件
运行前先确认
  • 代码位于支持 TypeScript 与 JSX 的 React 项目中。
  • 父组件会传入 title、done 和 onToggle 三个有效属性。
type TaskItemProps = {
  title: string;
  done: boolean;
  onToggle: () => void;
};

export function TaskItem({ title, done, onToggle }: TaskItemProps) {
  return <button onClick={onToggle}>{done ? "已完成" : "待完成"}:{title}</button>;
}
这段代码在做什么

组件通过 props 得到数据和动作,不需要知道任务保存在数组、API 还是数据库。

  1. TaskItemProps 先声明组件允许接收的输入及函数形状。
  2. 函数参数解构 props,并根据 done 选择显示文本。
  3. 点击 button 时只调用 onToggle,把修改决定交还给真正拥有任务数据的上层。
你应该观察到

组件根据不同 title 与 done 显示对应文字;点击后会调用父组件提供的回调,组件自身不会偷偷保存另一份任务状态。

02

AI COLLABORATION

AI 如何参与

要求 AI 先列出页面中的稳定组件边界,再写代码;对每个组件说明输入、输出和职责。

推荐协作顺序

  1. 1

    先给 AI 一张页面草图或现有 HTML,让它只画组件树。

  2. 2

    逐个确认组件的 props 和事件,再实现最小的 TaskItem。

  3. 3

    最后让它沿着数据流解释一次新增和切换完成,检查状态是否放对位置。

可直接使用的 Prompt
请把“个人学习任务应用”页面拆成 React 组件。先输出组件树和每个组件的职责、props、事件,不写代码;边界确认后再给 TaskItem 的 TypeScript 最小实现。不要把整个页面放进一个组件,也不要为每个标签建组件。
应该得到什么

清晰的组件树与单向数据流,TaskItem 只通过 props 显示任务并触发回调。

人工检查清单

  • 确认 props 类型清楚、列表 key 稳定,并且组件没有在渲染期间直接修改数据。
  • 要求 AI 为每个候选组件写出职责、props 和事件,再判断是否值得拆分。
  • 运行页面并用不同 props、空数据和点击事件验证组件,而不只检查默认截图。
03

COMMON TRAPS

常见误区

错误不是需要隐藏的失败,而是帮助你看清系统边界的证据。下面三类问题在 AI 辅助学习中最常出现。

误区 1

整个页面只有一个组件

你会看到
表单、列表、筛选和弹窗全挤在同一个函数里。
为什么发生
巨型组件把多个变化原因塞在一起,AI 修改一个区域时容易误伤其他状态与事件。
怎样纠正
按稳定业务单元拆分,让每个组件只承担一类变化。
误区 2

每个标签都建组件

你会看到
代码里出现 TitleText、SmallBox 等没有独立意义的包装。
为什么发生
把每个标签都组件化会制造大量没有语义的跳转,props 只是把原标记拆散,并未形成复用。
怎样纠正
没有复用、独立状态或明确职责的标签先留在父组件里。
误区 3

子组件直接修改父数据

你会看到
多个组件都能改同一数组,状态来源越来越难追。
为什么发生
子组件修改 props 会破坏单向数据流,多个位置都以为自己拥有同一份数据。
怎样纠正
数据留在共同父层,子组件通过回调表达用户动作。
04

HANDS-ON

动手任务

把静态页面重构为导航、标题、卡片列表和卡片四类组件。

准备条件
  • 完成 4.2「Node.js、npm 与构建工具」

跟着做

  1. 01

    创建 Task 类型,包含 id、title、done。

  2. 02

    实现只显示一条任务的 TaskItem。

  3. 03

    实现 TaskList,通过 map 渲染多个 TaskItem。

  4. 04

    实现 TaskForm,提交标题并通过回调上报。

  5. 05

    在页面组件组合三者,验证新增和完成操作。

完成标志

能读懂组件树,并知道数据是如何向下传递的。

加餐挑战

增加空列表提示组件,并保证没有任务时仍能理解下一步操作。

离开本课前,自问四件事

  • React、原生 Web 和构建工具分别负责什么?
  • 组件、JSX、props 与 state 之间是什么关系?
  • TaskItem 的输入和输出事件应该有哪些?
  • 我会用哪些信号判断某段界面值得拆成组件?
完成本课了吗?

确认完成后,会同步更新学习中心的课程学习进度。