13. 用Props让你的React组件动起来

课程初始代码
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
  

function App() {
  return (
    <div className="container">
      <Header />
      <Menu />
      <Footer />
    </div>
  );
}

function Header(){
  const style = {};

  return (
    <header className="header">
      <h1 style={style}>
        Fast React Pizza Co.
      </h1>
    </header>
  )
}

function Menu() {
  return (
    <main className="menu">
      <h2>Our Menu</h2>
      <Pizza />
      <Pizza />
      <Pizza />
      {/* 更多Pizza组件... */}
    </main>
  );
}

function Footer(){
  const hour = new Date().getHours();
  const openHour = 12;
  const closeHour = 22;
  const isOpen = hour >= openHour && hour <= closeHour;

  console.log(isOpen);
  
  return (
  <footer className="footer">
    {new Date().toLocaleDateString()}. We're currently open.
  </footer>
  )
}

function Pizza(){
    return <div>
        <img src="pizzas/spinaci.jpg"></img>
        <h3>Pizza Spinaci</h3>
        <p>Tomato, mozarella, spinach, and ricotta cheese</p>
    </div>
}

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
    <React.StrictMode>
        <App />
    </React.StrictMode>
);

React作为一个组件化的前端库,其强大之处在于可以构建可重用的组件。但如果每个组件都显示相同的内容,那重用的价值就大打折扣了。今天,我要和大家分享React中另一个核心概念:Props(属性)。Props是React组件之间通信的桥梁,特别是从父组件向子组件传递数据的关键机制。

Props是什么?

想象一下,Props就像父组件和子组件之间的专用通信通道。通过这个通道,父组件可以向子组件传递任何类型的数据:文本、数字、对象,甚至是其他React组件。

在我们的披萨应用示例中,目前所有的Pizza组件显示的都是相同的内容:

function Pizza(){
    return <div>
        <img src="pizzas/spinaci.jpg"></img>
        <h3>Pizza Spinaci</h3>
        <p>Tomato, mozarella, spinach, and ricotta cheese</p>
    </div>
}

这很局限,对吧?如果我们想展示不同种类的披萨,每种都有自己的名称、配料和图片,该怎么办?这正是Props派上用场的地方。

如何使用Props – 两步走

使用Props分为两个简单的步骤:

  1. 在父组件中传递Props到子组件
  2. 在子组件中接收并使用这些Props

让我们动手实践一下:

步骤1:传递Props

在Menu组件(父组件)中,我们将为Pizza组件(子组件)传递Props:

function Menu() {
  return (
    <main className="menu">
      <h2>Our Menu</h2>
      <Pizza 
        name="Pizza Spinaci" 
        ingredients="Tomato, mozarella, spinach, and ricotta cheese" 
        photoName="pizzas/spinaci.jpg"
        price="10"
      />
      {/* 更多Pizza组件... */}
    </main>
  );
}

注意我们如何将Props传递给Pizza组件:它们看起来就像HTML属性一样。每个Prop都有一个名称和一个值,这些值目前都是字符串。

步骤2:接收并使用Props

现在,我们需要修改Pizza组件来接收这些Props:

function Pizza(props) {
  console.log(props);
  return (
    <div>
      <img src={props.photoName} alt={props.name}></img>
      <h3>{props.name}</h3>
      <p>{props.ingredient}</p>
    </div>
  );
}

通过在函数参数中添加props,我们告诉React我们要接收传入的数据。通过控制台我们可以看到props是一个包含所有传入属性的对象。

在我们的例子中,它有四个属性:name、ingredients、photoName和price。

注意我们如何使用花括号{}来访问这些属性。花括号表示”我要在这里使用JavaScript”,让我们能够在JSX中嵌入JavaScript表达式。

Props的魔力:创建不同的披萨组件

现在,让我们展示Props的真正威力。我们可以使用相同的Pizza组件,但传入不同的数据,创建完全不同的披萨:

function Menu() {
  return (
    <main className="menu">
      <h2>Our Menu</h2>
      <Pizza 
        name="Pizza Spinaci" 
        ingredients="Tomato, mozarella, spinach, and ricotta cheese" 
        photoName="pizzas/spinaci.jpg"
        price="10"
      />
      <Pizza 
        name="Pizza Funghi" 
        ingredients="Tomato, mushrooms" 
        price="12"
        photoName="pizzas/funghi.jpg"
      />
      {/* 注意顺序可以不同,React会正确匹配属性名 */}
    </main>
  );
}

瞧!现在我们有两种不同的披萨了⬇️

每一个都有自己的名称、配料和图片,但都使用相同的Pizza组件结构。这就是组件复用的强大之处!

传递非字符串值

目前我们传递的所有Props都是字符串值,但如果想传递数字、布尔值、数组或对象呢?

我们需要使用花括号,告诉React”这是JavaScript,不是字符串”:

<Pizza 
  name="Pizza Margherita" 
  ingredients="Tomato, mozarella, basil" 
  photoName="pizzas/margherita.jpg"
  price={12} // 这是一个数字,不是字符串
/>

这一点非常重要!当我们想要在组件中进行数学运算时尤其如此:

function Pizza(props) {
  return (
    // ...其他代码
    <span>{props.price + 3}</span> // 如果price是字符串,"10" + 3 = "103"
                                   // 如果price是数字,10 + 3 = 13
  );
}

如果price传入为字符串,JavaScript会进行字符串连接;如果传入为数字,它会进行数学加法。所以确保根据你的需求传递正确的数据类型!

改进我们的披萨应用

让我们整合所学内容,改进我们的Pizza组件:

function Pizza(props) {
  return (
    <div className="pizza">
      <img src={props.photoName} alt={props.name}></img>
      <div>
        <h3>{props.name}</h3>
        <p>{props.ingredients}</p>
        <span>{props.price + 3}</span>
      </div>
    </div>
  );
}

function Menu() {
  return (
    <main className="menu">
      <h2>Our Menu</h2>
      <Pizza 
        name="Pizza Spinaci" 
        ingredients="Tomato, mozarella, spinach, and ricotta cheese" 
        photoName="pizzas/spinaci.jpg"
        price={10}
      />
      <Pizza 
        name="Pizza Funghi" 
        ingredients="Tomato, mushrooms" 
        price={12}
        photoName="pizzas/funghi.jpg"
      />
    </main>
  );
}

Props的强大之处

Props的强大远不止于此。你可以:

  1. 传递任何JavaScript值:字符串、数字、布尔值、数组、对象,甚至函数或其他React组件
  2. 传递不限数量的Props:根据组件的需要传递任意多的属性
  3. Props是只读的:子组件不能修改接收到的Props(这是React的单向数据流原则)
  4. 使用默认Props:设置默认值,以防某些Props没有传递

总结

Props是React中最基本也是最强大的概念之一。它们使我们能够:

  • 创建可重用的组件
  • 定制每个组件实例
  • 在组件之间传递数据
  • 保持组件之间的松耦合

在我们的披萨应用示例中,通过Props,我们能够用同一个Pizza组件展示不同种类的披萨,使我们的代码更简洁、更易于维护。 下次当你构建React应用时,记住Props的强大功能。它们是构建灵活、可重用组件的关键,让你的应用既有条理又易于扩展。


Comments

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注