React 你的第一个组件 —— 小白也能懂的通俗版
🧩 先搞懂:组件是什么?
组件就是可复用的 UI 积木。就像 HTML 有<h1>、<img>这些内置标签,React 让你可以自己造标签——比如<Profile />、<TableOfContents />、<NavigationHeader />。
⚡ 核心结论一句话
React 组件就是一个首字母大写的 JavaScript 函数,它返回一段 JSX(看起来像 HTML 的标签),React 负责把它渲染到页面上。
一、定义组件的三步法
第一步:导出组件
export default function Profile() { ... }export default是 JavaScript 标准语法,表示"这个文件的主要函数就是这个"。这样其他文件才能import它。
第二步:定义函数(注意大写!)
function Profile() { // ✅ P 必须大写! // ... }⚠️陷阱:组件名必须以大写字母开头,否则 React 不认识它,会当成普通 HTML 标签处理。
第三步:添加标签(JSX)
function Profile() { return ( <img src="https://react.dev/images/docs/scientists/MK3eW3As.jpg" alt="Katherine Johnson" /> ); }⚠️陷阱:如果
return和括号里的 JSX 不在同一行,必须用圆括号()包裹,否则 JS 会自动加分号导致代码失效。
// ✅ 一行搞定 return <img src="..." alt="..." />; // ✅ 多行必须加括号 return ( <img src="..." alt="..." /> ); // ❌ 错误:return 和多行 JSX 之间没括号 return <img src="..." alt="..." />;二、使用组件
定义完Profile后,可以在别的组件里直接用:
function Profile() { return ( <img src="https://react.dev/images/docs/scientists/MK3eW3As.jpg" alt="Katherine Johnson" /> ); } export default function Gallery() { return ( <section> <h1>了不起的科学家</h1> <Profile /> {/* 👈 用了三次!这就是复用 */} <Profile /> <Profile /> </section> ); }浏览器最终看到的是啥?
React 会把自定义标签展开成原生 HTML:
<section><h1>了不起的科学家</h1><imgsrc="..."alt="Katherine Johnson"/><imgsrc="..."alt="Katherine Johnson"/><imgsrc="..."alt="Katherine Johnson"/></section>怎么区分自定义标签和 HTML 标签?
| 写法 | React 的理解 |
|---|---|
<Profile /> | 大写开头 → 找名为Profile的组件 |
<img /> | 小写开头 → 原生 HTML 标签 |
<section> | 小写开头 → 原生 HTML 标签 |
三、嵌套和组织组件
父子关系
Gallery(父组件) ├── Profile(子组件 × 3) └── h1(原生标签)定义一次,到处复用。这是 React 最核心的价值之一。
文件组织策略
- 小项目 / 组件相关紧密→ 多个组件写在同一个文件
- 大项目→ 每个组件一个文件,通过
export/default import管理
src/ ├── App.js (根组件) ├── Gallery.js (含 Gallery + Profile) └── Navigation.js (独立文件)四、⚠️ 重要陷阱:不要在组件中定义组件
// 🔴 绝对不要这样做! export default function Gallery() { function Profile() { // ← 嵌套在另一个组件内部 return <img src="..." />; } return <Profile />; }为什么不行?
- 每次
Gallery重新渲染都会创建一个新的Profile函数 - 性能极差
- 会导致 state 丢失等诡异 bug
正确做法:所有组件都在顶层定义
// ✅ 正确:全部在顶层 export default function Gallery() { return ( <section> <Profile /> </section> ); } function Profile() { // ← 平级定义 return <img src="..." />; }五、万物皆组件
React 应用中每一块 UI 都是组件:
| 粒度 | 示例 |
|---|---|
| 最小 | <Button />、<Icon /> |
| 中等 | <Sidebar />、<Card /> |
| 最大 | <HomePage />、<Dashboard /> |
甚至只有一个页面用到一次的布局,也可以写成组件——这只是为了更好地组织代码。
基于 React 的框架更进一步
- CodeSandbox / Vite / CRA→ 根组件在
App.js - Next.js→ 根组件在
pages/index.js - 这些框架还会根据 React 组件自动生成服务器端 HTML,不需要等 JS 加载完才显示内容
🎯 面试高频追问
Q1:React 组件和普通 JavaScript 函数的区别是什么?
答:本质上都是函数,但有两个硬性规定:① 名称首字母必须大写;② 必须返回 JSX(或 null)。
Q2:为什么 return 后面要多行时必须加括号?
答:因为 JavaScript 有自动分号插入(ASI)机制。如果return和返回值不在同一行,JS 会在中间自动加分号,导致return后面什么也没返回。加括号可以避免这个问题。
Q3:什么是 JSX?
答:JSX 是 JavaScript 的语法扩展,允许你在 JS 文件中写类似 HTML 的标签。它在底层会被编译为 JavaScript 对象调用(React.createElement(...))。
Q4:组件可以嵌套定义吗?
答:不可以。嵌套定义会导致每次父组件渲染都重建子组件,性能差且引发 state 丢失等 bug。所有组件都应该在文件顶层声明。
Q5:浏览器最终看到的是 JSX 吗?
答:不是。浏览器只看到纯 HTML。React 会把 JSX 转换成 DOM 操作,最终渲染的是原生 HTML 元素。
📝 常见面试变体
- “如何定义一个 React 组件?”
- “JSX 和 HTML 有什么区别?”
- “为什么组件名要大写?”
- “简述 React 组件的渲染流程”
- “如何在项目中组织和管理组件?”
✅ 总结
你的第一个组件核心要点:
- 组件 =首字母大写的 JS 函数,返回 JSX 🔥
- 定义三步:
export default→function Name()→return (<JSX>) - 使用方式:(大写=组件,小写=HTML 标签)
- 定义一次,处处复用——这就是组件化思维
- 所有组件必须在顶层定义,禁止嵌套定义
- 多行
return必须用( )包裹,防止 ASI 坑 - 万物皆组件,从按钮到整页都是
