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 组件的渲染流程”
  • “如何在项目中组织和管理组件?”

✅ 总结

你的第一个组件核心要点:

  1. 组件 =首字母大写的 JS 函数,返回 JSX 🔥
  2. 定义三步:export defaultfunction Name()return (<JSX>)
  3. 使用方式:(大写=组件,小写=HTML 标签)
  4. 定义一次,处处复用——这就是组件化思维
  5. 所有组件必须在顶层定义,禁止嵌套定义
  6. 多行return必须用( )包裹,防止 ASI 坑
  7. 万物皆组件,从按钮到整页都是