React:用组件组织界面
框架不是魔法,而是一套组织规则。React 让界面围绕组件组织,并通过 props 组合和复用。
- 能读懂组件树,并知道数据是如何向下传递的。
- 原生 Web、框架和构建工具的关系
- 把静态页面重构为导航、标题、卡片列表和卡片四类组件。
- 完成 4.2「Node.js、npm 与构建工具」
FOUNDATION
必须理解
框架不是魔法,而是一套组织规则。React 让界面围绕组件组织,并通过 props 组合和复用。
React 用组件描述界面应该怎样随数据变化。它减少手动寻找和修改 DOM 的代码,让页面由可组合的函数与明确输入构成。
组件像积木模具:TaskItem 定义一条任务长什么样,传入不同 props 就得到不同内容;多个 TaskItem 组合成列表,再组合成页面。
任务应用拆为 TaskForm、TaskList、TaskItem 和 FilterBar;页面组件保存任务数据并把需要的信息传给子组件。
原生 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。
组件、JSX、props 与组合
props 是父组件交给子组件的输入,子组件应该把它当成只读数据。用户点了什么,可以通过回调告诉父组件,由真正拥有数据的地方决定怎么改。
基础概念
组件是可组合的界面单元,通常用函数根据输入返回界面描述;JSX 是在 JavaScript 中描述元素树的语法;props 是父组件传入的只读数据。
进一步理解
组件名称用大写开头,让 React 区分自定义组件与原生标签。父组件通过 props 传值和回调,子组件读取它们来显示或通知事件,不应直接修改 props。
组合允许父组件把内容嵌入子组件,也允许同一组件使用不同数据重复渲染。组件每次计算应尽量保持纯粹,相同输入得到相同界面。
TaskList 把每条任务作为 props 交给 TaskItem;TaskItem 显示标题和完成状态,并通过 onToggle 通知上层用户点击。
props 与 state 不同:props 由外部传入,state 是组件需要记住并可更新的信息;两者都能影响渲染。
这一小节记住:组件通过 props 接收事实,通过组合形成页面,通过回调报告事件。
按业务单元拆分,而不是拆得越细越好
一张任务卡、一个任务列表、一个新增表单都算清楚的业务单元,适合做组件。但如果只是包了一层文字,又没有独立职责,就没必要单独建文件。
基础概念
组件边界应围绕独立职责、可重复结构或独立变化原因划分。拆分目标是降低理解成本,而不是让文件数量最大化。
进一步理解
一个组件最好能用一句话说明职责,并拥有清楚输入与输出。任务卡、筛选栏和新增表单往往有独立语义;只有一层样式包装的 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 还是数据库。
- TaskItemProps 先声明组件允许接收的输入及函数形状。
- 函数参数解构 props,并根据 done 选择显示文本。
- 点击 button 时只调用 onToggle,把修改决定交还给真正拥有任务数据的上层。
组件根据不同 title 与 done 显示对应文字;点击后会调用父组件提供的回调,组件自身不会偷偷保存另一份任务状态。
AI COLLABORATION
AI 如何参与
要求 AI 先列出页面中的稳定组件边界,再写代码;对每个组件说明输入、输出和职责。
推荐协作顺序
- 1
先给 AI 一张页面草图或现有 HTML,让它只画组件树。
- 2
逐个确认组件的 props 和事件,再实现最小的 TaskItem。
- 3
最后让它沿着数据流解释一次新增和切换完成,检查状态是否放对位置。
请把“个人学习任务应用”页面拆成 React 组件。先输出组件树和每个组件的职责、props、事件,不写代码;边界确认后再给 TaskItem 的 TypeScript 最小实现。不要把整个页面放进一个组件,也不要为每个标签建组件。
清晰的组件树与单向数据流,TaskItem 只通过 props 显示任务并触发回调。
人工检查清单
- 确认 props 类型清楚、列表 key 稳定,并且组件没有在渲染期间直接修改数据。
- 要求 AI 为每个候选组件写出职责、props 和事件,再判断是否值得拆分。
- 运行页面并用不同 props、空数据和点击事件验证组件,而不只检查默认截图。
COMMON TRAPS
常见误区
错误不是需要隐藏的失败,而是帮助你看清系统边界的证据。下面三类问题在 AI 辅助学习中最常出现。
整个页面只有一个组件
- 你会看到
- 表单、列表、筛选和弹窗全挤在同一个函数里。
- 为什么发生
- 巨型组件把多个变化原因塞在一起,AI 修改一个区域时容易误伤其他状态与事件。
- 怎样纠正
- 按稳定业务单元拆分,让每个组件只承担一类变化。
每个标签都建组件
- 你会看到
- 代码里出现 TitleText、SmallBox 等没有独立意义的包装。
- 为什么发生
- 把每个标签都组件化会制造大量没有语义的跳转,props 只是把原标记拆散,并未形成复用。
- 怎样纠正
- 没有复用、独立状态或明确职责的标签先留在父组件里。
子组件直接修改父数据
- 你会看到
- 多个组件都能改同一数组,状态来源越来越难追。
- 为什么发生
- 子组件修改 props 会破坏单向数据流,多个位置都以为自己拥有同一份数据。
- 怎样纠正
- 数据留在共同父层,子组件通过回调表达用户动作。
HANDS-ON
动手任务
把静态页面重构为导航、标题、卡片列表和卡片四类组件。
- 完成 4.2「Node.js、npm 与构建工具」
跟着做
- 01
创建 Task 类型,包含 id、title、done。
- 02
实现只显示一条任务的 TaskItem。
- 03
实现 TaskList,通过 map 渲染多个 TaskItem。
- 04
实现 TaskForm,提交标题并通过回调上报。
- 05
在页面组件组合三者,验证新增和完成操作。
能读懂组件树,并知道数据是如何向下传递的。
增加空列表提示组件,并保证没有任务时仍能理解下一步操作。
离开本课前,自问四件事
- React、原生 Web 和构建工具分别负责什么?
- 组件、JSX、props 与 state 之间是什么关系?
- TaskItem 的输入和输出事件应该有哪些?
- 我会用哪些信号判断某段界面值得拆成组件?
确认完成后,会同步更新学习中心的课程学习进度。