第10章 组件与Props

React 组件的基本概念和属性传递

作者:zyyc-0336  |  日期:2026-06-12

前置依赖:第9章 React 介绍与 JSX

下一章:第11章 State 与交互

📋 学习路径建议
  1. 先学 10.1.1(函数组件定义),掌握组件的基本写法
  2. 再学 10.1.2-10.1.3(Props 传递和默认值),学会组件之间传数据
  3. 最后学 10.1.4(children),理解"嵌套内容"的传递
⚠️ 常见错误提示
  • 组件名必须大写字母开头<PostCard /> ✅,<postCard />
  • Props 是只读的,组件内部不能修改 Props
  • 传 Props 时,字符串用引号,其他类型用 {}title="Hello" vs count={'{'}5{'}'}
  • 组件返回的 JSX 只能有一个根元素

10.1 组件与 Props

组件是 React 的积木,Props 是积木之间的接口

10.1.1 函数组件定义

组件就是一个返回 JSX 的函数。它接收数据(Props),输出一段界面。就像一个"机器"——你给它原料(数据),它给你产品(界面)。

// 最简单的组件
function Welcome() {
    return <h1>欢迎来到我的博客!</h1>;
}

// 使用组件(像标签一样用)
<Welcome />

组件的命名规则

规则正确错误
大写字母开头PostCardpostCard
有意义的名字ArticleListMyComponent
驼峰命名NavBarnav-bar
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>组件定义示例</title>
</head>
<body>
    <div id="root"></div>
    <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>

    <script type="text/babel">
        // ========== 组件定义 ==========

        // 博客标题组件
        function BlogTitle() {
            return <h1>📝 我的技术博客</h1>;
        }

        // 博客简介组件
        function BlogIntro() {
            return (
                <p style={{ color: '#666', fontSize: '16px' }}>
                    分享前端开发知识,记录学习笔记。
                </p>
            );
        }

        // 底部版权组件
        function Footer() {
            return (
                <footer style={{ marginTop: '40px', color: '#999', fontSize: '14px' }}>
                    <hr />
                    <p>© 2026 我的博客. All rights reserved.</p>
                </footer>
            );
        }

        // 组合使用
        function App() {
            return (
                <div style={{ maxWidth: '600px', margin: '0 auto', padding: '20px' }}>
                    <BlogTitle />
                    <BlogIntro />
                    <hr />
                    <p>这里将来会放文章列表...</p>
                    <Footer />
                </div>
            );
        }

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

代码逐行讲解

代码说明
function BlogTitle()定义组件——一个返回 JSX 的函数
return <h1>...</h1>返回界面结构
<BlogTitle />使用组件——像 HTML 标签一样写
<App />在顶层组合所有子组件

💡 组件就像"自定义标签"。定义一次,到处使用。

10.1.2 Props 传递

Props(properties 的缩写)是父组件传给子组件的数据。就像函数的参数一样,让组件变得灵活。

// 子组件接收 Props
function PostCard(props) {
    return <h2>{'{'}props.title{'}'}</h2>;
}

// 父组件传递 Props
<PostCard title="JavaScript入门" />
// 解构写法(推荐,更清晰)
function PostCard({ title, excerpt, date, author }) {
    return (
        <div style={{ border: '1px solid #e0e0e0', borderRadius: '8px',
                     padding: '20px', marginBottom: '16px' }}>
            <h2>{'{'}title{'}'}</h2>
            <p>✍️ {'{'}author{'}'} · 📅 {'{'}date{'}'}</p>
            <p>{'{'}excerpt{'}'}</p>
            <a href="#">阅读全文 →</a>
        </div>
    );
}

// 父组件传递 Props
function App() {
    return (
        <div>
            <h1>文章列表</h1>
            <PostCard
                title="JavaScript 入门指南"
                author="小明"
                date="2026-06-01"
                excerpt="零基础学习 JavaScript 的基础语法..."
            />
        </div>
    );
}

Props 传递方式

方式语法示例
字符串prop="值"title="Hello"
数字prop={'{数值}'}count={'{5}'}
布尔值prop={'{true}'} 或简写 propisPublished={'{true}'}
对象prop={'{对象}'}style={'{{ color: \'red\' }}'}
数组prop={'{数组}'}items={'{[\'a\', \'b\']}'}
函数prop={'{函数}'}onClick={'{() => alert(1)}'}

⚠️ 新手易错:Props 是只读的,子组件不能修改 Props。这就像函数参数——你可以用它,但不能改它。想改就用 State(下一章讲)。

10.1.3 默认值与类型

当父组件没有传某个 Prop 时,子组件可以设置默认值。

// 设置默认值(解构时直接赋值)
function PostCard({
    title = '无标题',
    author = '匿名',
    date = '未知日期',
    excerpt = '暂无摘要',
    views = 0
}) {
    return (
        <div>
            <h3>{'{'}title{'}'}</h3>
            <p>{'{'}author{'}'} · {'{'}date{'}'} · 👁️ {'{'}views{'}'} 次浏览</p>
            <p>{'{'}excerpt{'}'}</p>
        </div>
    );
}

function App() {
    return (
        <div>
            {/* 传了所有 Props */}
            <PostCard title="完整文章" author="小明"
                date="2026-06-12" excerpt="这篇文章传了所有 Props"
                views={1500} />

            {/* 只传部分,其余用默认值 */}
            <PostCard title="部分 Props" excerpt="只传了标题和摘要" />

            {/* 什么都不传,全部用默认值 */}
            <PostCard />
        </div>
    );
}

运行结果

┌──────────────────────────────┐
│ 完整文章                      │
│ 小明 · 2026-06-12 · 👁️ 1500  │
│ 这篇文章传了所有 Props         │
└──────────────────────────────┘

┌──────────────────────────────┐
│ 部分 Props                    │
│ 匿名 · 未知日期 · 👁️ 0        │
│ 只传了标题和摘要               │
└──────────────────────────────┘

┌──────────────────────────────┐
│ 无标题                        │
│ 匿名 · 未知日期 · 👁️ 0        │
│ 暂无摘要                      │
└──────────────────────────────┘

10.1.4 children

children 是一个特殊的 Prop——组件标签之间的内容。就像 HTML 标签可以包含内容一样,React 组件也可以。

// children 就是标签之间的内容
<Card>
    <h1>这是 children</h1>
    <p>这也是 children</p>
</Card>
// ========== 卡片容器组件 ==========
// children 是"中间的内容",由父组件决定
function Card({ title, children }) {
    return (
        <div style={{
            border: '1px solid #ddd', borderRadius: '8px',
            padding: '20px', marginBottom: '16px',
            boxShadow: '0 2px 4px rgba(0,0,0,0.1)'
        }}>
            <h2>{'{'}title{'}'}</h2>
            {/* children 在这里渲染 */}
            <div>{'{'}children{'}'}</div>
        </div>
    );
}

// ========== 按钮组件 ==========
function Button({ variant = 'primary', children, ...rest }) {
    let colors = {
        primary: { bg: '#3498db', color: 'white' },
        danger:  { bg: '#e74c3c', color: 'white' },
        success: { bg: '#2ecc71', color: 'white' }
    };
    let style = colors[variant] || colors.primary;

    return (
        <button style={{
            padding: '8px 16px', backgroundColor: style.bg,
            color: style.color, border: 'none',
            borderRadius: '4px', cursor: 'pointer',
            marginRight: '8px'
        }} {'{'}...rest{'}'}>
            {'{'}children{'}'}
        </button>
    );
}

// ========== 使用 ==========
function App() {
    return (
        <div>
            <Card title="文章标题">
                <p>这是卡片的内容,通过 children 传入。</p>
                <p>可以放任何 JSX 内容。</p>
            </Card>

            <Card title="操作面板">
                <p>请选择操作:</p>
                <Button variant="primary">确认</Button>
                <Button variant="danger">删除</Button>
                <Button variant="success">保存</Button>
            </Card>
        </div>
    );
}

children 的使用场景

场景说明
容器组件<Card> 只管样式,不管内容
按钮组件<Button> 只管样式和行为,文字由 children 决定
布局组件<Layout> 只管布局,内容随意
弹窗组件<Modal> 只管弹窗框架,内容自定义

💡 children 让组件变成"容器"——你决定结构和样式,使用者决定内容。这就是组件复用的核心思想。

本章复盘——组件与 Props 核心要点

要点说明
组件定义函数组件就是返回 JSX 的函数,大写字母开头
Props父组件传给子组件的数据,只读不可修改
解构 Propsfunction Comp({'{ title, author }'}) {} 推荐写法
默认值解构时直接赋默认值 title = '无标题'
children特殊 Prop,代表组件标签之间的内容
使用组件<PostCard title="Hello" />,像 HTML 标签一样

下一章预告(第11章):我们将学习useEffect 与生命周期——副作用处理、数据获取和组件生命周期管理。

本文档由 zyyc-0336 编写,最后更新:2026-06-14