React父子组件通信:Props怎么用?如何从父组件向子组件传递数据?

系列回顾:

在上一篇《React核心概念:State是什么?》中,我们学习了如何使用useState让一个组件拥有自己的内部数据(State),并通过一个计数器案例,实现了组件的自我更新。这很棒,但一个真实的React应用是由许多组件组合而成的,就像搭积木一样。如果这些"积木"之间不能互相沟通、传递信息,那我们就无法搭建出复杂的结构。

欢迎来到React学习的第三站!

今天,我们要学习组件之间最基本、最重要的一种沟通方式:父组件向子组件传递数据 。而实现这种沟通的"信使",就是 Props

什么是Props?

Props (是 Properties 的缩CR) 就像是你在调用一个JavaScript函数时传递的参数。在React中,它就是父组件在调用子组件时,传递给子组件的"属性"或"数据"。

核心思想:

  • 父组件拥有数据。
  • 父组件通过属性的方式,把数据"塞"给子组件。
  • 子组件 通过一个叫做props的对象,接收并使用这些数据。

一个重要的原则:Props是只读的。 子组件只能读取和使用从父组件传来的Props,但绝对不能修改它。这保证了数据流的单向性(从上到下),让应用状态更可预测。


实战:创建一个用户卡片

让我们通过一个非常常见的案例------"用户卡片"------来学习Props的用法。我们将创建一个UserProfile子组件,它专门用来显示用户的头像和名字。而用户的具体信息(头像URL和名字)将由它的父组件App来提供。

第一步:创建子组件 UserProfile.jsx

  1. 在你的项目里,找到 src 文件夹。

  2. src 文件夹下,右键 -> 新建文件,命名为 UserProfile.jsx

  3. 将下面的代码复制到 UserProfile.jsx 文件中:

    jsx 复制代码
    // src/UserProfile.jsx
    
    function UserProfile(props) {
      // 'props' 是一个对象,包含了父组件传递过来的所有属性
      console.log(props); // 可以在浏览器控制台看看 props 长什么样
      
      return (
        <div className="user-card">
          <img src={props.avatarUrl} alt={props.name} className="avatar" />
          <h2 className="user-name">{props.name}</h2>
        </div>
      );
    }
    
    export default UserProfile;

    代码解释:

    • 我们的UserProfile组件接收一个参数props。React会自动把父组件传递的所有属性打包成一个对象,放进这个props里。
    • 在JSX中,我们通过props.avatarUrlprops.name来使用这些数据。
    • className是React中用来指定CSS类名的方式,它对应HTML中的class属性。

第二步:在父组件 App.jsx 中使用子组件并传递Props

现在,回到我们的App.jsx文件。我们将在这里"调用"刚刚创建的UserProfile组件,并像给HTML标签添加属性一样,把数据传递给它。

  1. 清空 App.jsx 并写入以下代码:

    jsx 复制代码
    // src/App.jsx
    
    import './App.css';
    import UserProfile from './UserProfile'; // 1. 导入子组件
    
    function App() {
      const userInfo = {
        name: 'React 小白',
        avatarUrl: 'https://zh-hans.react.dev/images/logo.svg' // 使用React官方Logo作为头像
      };
    
      return (
        <div>
          <h1>我的用户卡片</h1>
          {/* 2. 使用子组件,并像HTML属性一样传递props */}
          <UserProfile 
            name={userInfo.name} 
            avatarUrl={userInfo.avatarUrl} 
          />
        </div>
      );
    }
    
    export default App;

    代码解释:

    1. import UserProfile from './UserProfile';: 我们首先需要像导入普通模块一样,把子组件导入进来。
    2. 在JSX中,我们像使用一个自定义的HTML标签一样使用<UserProfile />
    3. 最关键的一步: 我们添加了nameavatarUrl这两个"属性"。
      • name={userInfo.name}: 这表示我们要传递一个名为name的prop,它的值是userInfo.name这个JavaScript变量的值。
      • avatarUrl={userInfo.avatarUrl}: 同理,传递一个名为avatarUrl的prop。

第三步:添加一点样式

为了让卡片更好看,我们给App.css添加一点简单的样式。打开src/App.css,用下面的代码替换原有内容:

css 复制代码
/* src/App.css */
.user-card {
  border: 1px solid #ccc;
  border-radius: 8px;
  padding: 16px;
  text-align: center;
  width: 200px;
  margin: 20px auto;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.avatar {
  width: 100px;
  height: 100px;
  border-radius: 50%;
  object-fit: cover;
}

.user-name {
  margin-top: 12px;
  color: #333;
}

第四步:查看效果

现在,保存所有文件,回到你的浏览器。你应该能看到一个漂亮的用户卡片,上面有React的Logo和"React 小白"这个名字。

你已经成功地实现了父组件到子组件的数据传递!

Props的更多用法

1. 传递不同类型的数据

Props不仅可以传递字符串,还可以传递任何JavaScript支持的类型。

jsx 复制代码
<UserProfile
  name="Tom"          // 字符串
  age={25}             // 数字 (注意使用花括号)
  isMember={true}      // 布尔值
  hobbies={['coding', 'reading']} // 数组
  profile={{ job: 'developer' }} // 对象
  sayHi={() => alert('Hello!')} // 函数
/>

2. 使用Props解构赋值,让代码更简洁

在子组件中,每次都写props.name有点繁琐。我们可以使用JS的解构赋值来简化它。

修改UserProfile.jsx

jsx 复制代码
// function UserProfile(props) {
// 变为:
function UserProfile({ name, avatarUrl }) { // 直接在这里解构
  return (
    <div className="user-card">
      {/* 现在可以直接使用变量名 */}
      <img src={avatarUrl} alt={name} className="avatar" />
      <h2 className="user-name">{name}</h2>
    </div>
  );
}

这样代码是不是清爽多了?这是现代React开发中非常推荐的做法。


总结与思考

今天,我们掌握了组件化开发中最重要的一环------组件间的通信。回顾一下核心知识:

  1. Props是什么? 它是父组件传递给子组件的数据,就像函数的参数。
  2. 如何传递Props? 在使用子组件时,像写HTML属性一样把数据"塞"进去:<MyComponent propName={value} />
  3. 如何接收Props? 子组件的函数接收一个props对象作为参数,通过props.propName来访问数据。
  4. Props是只读的! 子组件不能修改从父组件接收到的Props。

我们现在已经学会了组件的"自力更生"(State)和"向父辈求助"(Props)。但是,一个有生命力的应用,还需要能响应用户的各种操作,比如点击、输入等等。

在下一篇文章 《React事件处理:如何给按钮绑定onClick点击事件?》 中,我们将学习如何让我们的组件"听懂"用户的指令,从而构建出真正可交互的应用。我们下期再会!

相关推荐
cos4 分钟前
FE Bits 前端周周谈 Vol.1|Hello World、TanStack DB 首个 Beta 版发布
前端·javascript·css
饺子不放糖6 分钟前
CSS的float布局,让我怀疑人生
前端
阳光是sunny22 分钟前
走进AI(1):细说RAG、MCP、Agent、Function Call
前端·ai编程
剪刀石头布啊31 分钟前
var、let、const与闭包、垃圾回收
前端·javascript
剪刀石头布啊33 分钟前
js常见的单例
前端·javascript
剪刀石头布啊33 分钟前
数据口径
前端·后端·程序员
剪刀石头布啊37 分钟前
http状态码大全
前端·后端·程序员
剪刀石头布啊39 分钟前
iframe通信、跨标签通信的常见方案
前端·javascript·html
宇之广曜1 小时前
搭建 Mock 服务,实现前端自调
前端·mock
yuko09311 小时前
【手机验证码】+86垂直居中的有趣问题
前端