初始代码(点击展开)
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
const pizzaData = [
{
name: "Focaccia",
ingredients: "Bread with italian olive oil and rosemary",
price: 6,
photoName: "pizzas/focaccia.jpg",
soldOut: false,
},
{
name: "Pizza Margherita",
ingredients: "Tomato and mozarella",
price: 10,
photoName: "pizzas/margherita.jpg",
soldOut: false,
},
{
name: "Pizza Spinaci",
ingredients: "Tomato, mozarella, spinach, and ricotta cheese",
price: 12,
photoName: "pizzas/spinaci.jpg",
soldOut: false,
},
{
name: "Pizza Funghi",
ingredients: "Tomato, mozarella, mushrooms, and onion",
price: 12,
photoName: "pizzas/funghi.jpg",
soldOut: false,
},
{
name: "Pizza Salamino",
ingredients: "Tomato, mozarella, and pepperoni",
price: 15,
photoName: "pizzas/salamino.jpg",
soldOut: true,
},
{
name: "Pizza Prosciutto",
ingredients: "Tomato, mozarella, ham, aragula, and burrata cheese",
price: 18,
photoName: "pizzas/prosciutto.jpg",
soldOut: false,
},
];
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
name="Pizza Spinaci"
ingredient="Tomato, mozarella, spinach, and ricotta cheese"
photoName="pizzas/spinaci.jpg"
price={10}
/>
<Pizza
name="Pizza Funghi"
ingredient="Tomato, mushrooms"
price={12}
photoName="pizzas/funghi.jpg"
/>
</main>
);
}
function Pizza(props) {
console.log(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 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>
);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
今天我想深入探讨React开发中最常见的任务之一:渲染列表。这是将是你在项目中会做上百次的事情。
“渲染列表”是什么意思?
简单来说,渲染列表就是获取一个数据数组,并为数组中的每个元素创建一个组件。我们不是手动编写每个组件,而是希望React根据我们的数据动态生成它们。
例如,假设我们有一个披萨对象的数组,我们想在UI中将每个披萨显示为一个组件。如果我们数组中有四个披萨,我们应该看到四个组件。如果我们在数组中添加两个更多的披萨,两个新组件应该自动出现。
JavaScript .map() 方法的威力
这就是React的魅力所在 – 你不需要为此学习任何特殊的React语法。你只需要使用现有的JavaScript知识,特别是.map()方法。
让我们修改一下代码:
const pizzaData = [
{
name: "Focaccia",
ingredients: "Bread with italian olive oil and rosemary",
price: 6,
photoName: "pizzas/focaccia.jpg",
soldOut: false,
},
{
name: "Pizza Margherita",
ingredients: "Tomato and mozarella",
price: 10,
photoName: "pizzas/margherita.jpg",
soldOut: false,
},
// 更多披萨...
];
function Menu() {
return (
<main className="menu">
<h2>Our Menu</h2>
<ul className="pizzas">
{pizzaData.map((pizza) => (
<Pizza pizzaObject={pizza} key={pizza.name} />
))}
</ul>
</main>
);
}这里发生了什么?我们获取pizzaData数组并使用.map()将每个披萨对象转换为一个Pizza组件。然后React按顺序渲染所有这些组件。
Pizza组件
我们的Pizza组件接收披萨对象作为prop并显示其属性:
function Pizza(props) {
return (
<li className="pizza">
<img src={props.pizzaObject.photoName} alt={props.pizzaObject.name} />
<div>
<h3>{props.pizzaObject.name}</h3>
<p>{props.pizzaObject.ingredients}</p>
<span>{props.pizzaObject.price}</span>
</div>
</li>
);
}至关重要的key属性
你注意到我们.map()函数中的key={pizza.name}了吗?这在React中渲染列表时是必不可少的。
当React渲染列表时,它需要一种方法来识别哪些项目已更改、添加或删除。key属性帮助React跟踪每个组件,使其能够高效地更新UI。
你的key应该是:
- 在兄弟组件中唯一
- 稳定(不变的)
- 可预测的
在我们的例子中,我们使用披萨名称作为key,假设每个披萨都有唯一的名称。在实际应用中,你可能会使用数据库ID或其他唯一标识符。
如果你忘记包含key,React会在控制台中给你一个警告:

“警告:列表中的每个子项都应该有一个唯一的’key’属性。”
使用语义化HTML
注意我们如何将披萨列表包装在<ul>元素(无序列表)中,并且每个Pizza组件都包装在<li>元素(列表项)中。这是正确的语义化HTML,对于可访问性和SEO非常重要。
<ul className="pizzas">
{pizzaData.map((pizza) => (
<Pizza pizzaObject={pizza} key={pizza.name} />
))}
</ul>为什么不用forEach()?
你可能想知道为什么我们使用.map()而不是.forEach()。关键区别是.map()创建并返回一个新数组,而.forEach()只是循环遍历数组而不返回任何内容。
在JSX中,我们需要有元素来渲染,而.map()正好给我们提供了React可以渲染的JSX元素数组。
最终代码
我们修改后完整代码和效果可能如下所示:
完整代码(点击展开)
import React from "react";
import ReactDOM from "react-dom/client";
import "./index.css";
const pizzaData = [
{
name: "Focaccia",
ingredients: "Bread with italian olive oil and rosemary",
price: 6,
photoName: "pizzas/focaccia.jpg",
soldOut: false,
},
{
name: "Pizza Margherita",
ingredients: "Tomato and mozarella",
price: 10,
photoName: "pizzas/margherita.jpg",
soldOut: false,
},
{
name: "Pizza Spinaci",
ingredients: "Tomato, mozarella, spinach, and ricotta cheese",
price: 12,
photoName: "pizzas/spinaci.jpg",
soldOut: false,
},
{
name: "Pizza Funghi",
ingredients: "Tomato, mozarella, mushrooms, and onion",
price: 12,
photoName: "pizzas/funghi.jpg",
soldOut: false,
},
{
name: "Pizza Salamino",
ingredients: "Tomato, mozarella, and pepperoni",
price: 15,
photoName: "pizzas/salamino.jpg",
soldOut: true,
},
{
name: "Pizza Prosciutto",
ingredients: "Tomato, mozarella, ham, aragula, and burrata cheese",
price: 18,
photoName: "pizzas/prosciutto.jpg",
soldOut: false,
},
];
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>
<ul className="pizzas">
{pizzaData.map((pizza) => (
<Pizza pizzaObj={pizza} key={pizza.name}/>
))}
</ul>
{/* <Pizza
name="Pizza Spinaci"
ingredient="Tomato, mozarella, spinach, and ricotta cheese"
photoName="pizzas/spinaci.jpg"
price={10}
/>
<Pizza
name="Pizza Funghi"
ingredient="Tomato, mushrooms"
price={12}
photoName="pizzas/funghi.jpg"
/> */}
</main>
);
}
function Pizza(props) {
console.log(props);
return (
<li className="pizza">
<img src={props.pizzaObj.photoName} alt={props.pizzaObj.name}></img>
<div>
<h3>{props.pizzaObj.name}</h3>
<p>{props.pizzaObj.ingredients}</p>
<span>{props.pizzaObj.price}</span>
</div>
</li>
);
}
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>
);
}
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);

总结
渲染列表是React的基本技能,其美妙之处在于它的简单性。通过利用JavaScript的.map()方法,我们可以根据数据动态渲染组件,使我们的应用程序更加灵活和可维护。
记住这些关键点:
- 使用
.map()将数据数组转换为组件数组 - 始终为每个项目提供唯一的
key属性 - 在适当的情况下使用语义化HTML(如
<ul>和<li>) - 考虑将整个对象作为props传递,以获得更简洁的代码


发表回复