🐸 青蛙编程网
首页 / 前端 / React / 3. 组件基础

3. 组件基础

这是什么:React 组件 = 一个返回 JSX 的函数,没有模板、没有多文件格式,一个函数就是一个组件。

为什么用:上一章把整页写在一个组件里,再多几块就乱了。把页面拆成小函数组件,各块只管自己那块,复用和分工都变简单。

如何用:本章先写一个 TaskItem 组件,再用它在父组件里循环渲染,最后用 children 学会「往标签中间装内容」。

3.1 函数组件:一整页就是几个函数

任务条目拆出来,页面立刻清爽——整段可跑:

<!DOCTYPE html>
<html lang='zh-CN'>
<head>
  <meta charset='utf-8'>
  <script src='https://registry.npmmirror.com/react/18.3.1/files/umd/react.production.min.js'></script>
  <script src='https://registry.npmmirror.com/react-dom/18.3.1/files/umd/react-dom.production.min.js'></script>
  <script src='https://registry.npmmirror.com/@babel/standalone/7.29.11/files/babel.min.js'></script>
</head>
<body>
  <div id='root'></div>

  <script type='text/babel' data-presets='react'>
    function TaskItem({ text }) {        // 组件名必须大写开头:小写会被当 HTML 标签
      return <li>{text}</li>
    }

    function App() {                     // 函数组合:App 里装小型组件
      return (
        <ul>
          <TaskItem text='学 React' />
          <TaskItem text='写教程' />
        </ul>
      )
    }

    ReactDOM.createRoot(document.getElementById('root')).render(<App />)
  </script>
</body>
</html>

你会看到:两条任务「学 React」「写教程」——<TaskItem /> 用起来像 HTML 标签,其实是函数。

要点:

  • 组件名必须大写开头(<TaskItem> 是组件、<taskitem> 会被当 HTML 标签)
  • 参数解构 { text } 接外部传入数据(就是 props,下一章细讲)
  • 免构建阶段一个 <text/babel> 块可以放多个组件;工程化阶段是一个文件一个组件、文件名与组件名相同

3.2 组件即函数:真正的复用 + children 通用外皮

Welcome 复用与 Card 组合放进一页看个痛快:

<!DOCTYPE html>
<html lang='zh-CN'>
<head>
  <meta charset='utf-8'>
  <script src='https://registry.npmmirror.com/react/18.3.1/files/umd/react.production.min.js'></script>
  <script src='https://registry.npmmirror.com/react-dom/18.3.1/files/umd/react-dom.production.min.js'></script>
  <script src='https://registry.npmmirror.com/@babel/standalone/7.29.11/files/babel.min.js'></script>
</head>
<body>
  <div id='root'></div>

  <script type='text/babel' data-presets='react'>
    function Welcome({ name }) {
      return <h2>欢迎,{name}!</h2>
    }

    function Card({ title, children }) {
      return (
        <div style={{ border: '1px solid #ddd', padding: '12px', marginTop: '12px' }}>
          <h3>{title}</h3>
          {children}        {/* 承接标签中间的内容(Vue 的 slot) */}
        </div>
      )
    }

    function App() {
      return (
        <div>
          <Welcome name='青蛙' />
          <Welcome name='熊猫' />
          <Card title='公告'>
            <p>这里放任意 JSX</p>
            <p>第二行也照样收</p>
          </Card>
        </div>
      )
    }

    ReactDOM.createRoot(document.getElementById('root')).render(<App />)
  </script>
</body>
</html>

你会看到:两行「欢迎,青蛙!」「欢迎,熊猫!」——组件 = 带 UI 输出的函数,传什么 props 就画什么画面;下面还有一张带「公告」标题的卡片,里面的内容就是 children(Vue 里的 <slot>)。

3.3 页面组织

免构建阶段,所有组件都在同一个 <text/babel> 块里,位置毫无讲究;但工程化(Vite)阶段的目录习惯值得先见一眼:

src/
├── App.jsx          # 根组件
├── components/      # 一般组件
│   ├── TaskItem.jsx
│   └── TaskList.jsx
└── main.jsx         # 启动器

每章页面末尾那行就是启动器本体:ReactDOM.createRoot(document.getElementById('root')).render(<App />)——Vue 的「index.html 壳 → main 启动 → App 根 → 子树」React 一模一样,只是启动函数叫 createRoot。

3.4 组合:一切靠组件树

组件可以无限 nesting:Card 的 children 里还能再装 Card 或 TaskItem——页面上每个可见块都是树上一个组件节点。动手改一节里你会亲手做出三层树。

3.5 动手改

  1. 在 3.1 页面写 Badge 组件,传入 text 显示彩色角标
  2. 用 <Card title='技能'> 包住 Badge × 3,复用卡片
  3. 给 Card 加一个可选 props footer(不传时 {footer} 就是 undefined,验证 JSX 不渲染它)

3.6 小结

  • 组件 = 返回 JSX 的大写函数,props 当参数
  • children 承接嵌套内容,复用与组合都靠它
  • 启动三行:开启容器 + createRoot + render;页面组织免构建阶段全在一块

下一章:state 与事件处理 🐸

📥 下载本章代码

ZIP 内含本章全部代码文件与说明,解压即用,与教程内容同步生成。