第八部分:第四节 - 列表渲染与条件渲染:根据订单显示不同内容
在构建用户界面时,经常需要根据数据动态地渲染内容,比如显示一个列表(菜单列表、订单列表)或者根据条件显示/隐藏某个元素(库存不足提示、登录/注册按钮)。React 提供了灵活的方式来处理这些场景。这就像点餐系统需要根据后台传来的菜单数据动态生成菜品列表,或者根据菜品的库存状态显示“有货”或“售罄”。
渲染列表数据 (map
方法):
在 React 中渲染一个数据列表,最常用的方法是使用 JavaScript 数组的 map()
方法。map()
方法遍历数组中的每个元素,并为每个元素返回一个 React 元素(通常是 JSX)。
// src/components/MenuList.jsx
import React from 'react';
import MenuItem from './MenuItem'; // 导入 MenuItem 组件function MenuList({ menuItems }) { // 接收菜品数组作为 propsreturn (<div><h2>菜单</h2><ul>{/* 使用 map 方法遍历 menuItems 数组 */}{menuItems.map(item => (// 为列表中的每个元素渲染一个 MenuItem 组件// !! key 属性非常重要 !!<MenuItem key={item.id} name={item.name} price={item.price} />))}</ul></div>);
}export default MenuList;
key
属性:
在渲染列表时,为每个列表项提供一个唯一且稳定的 key
属性是非常重要的。key
帮助 React 识别哪些列表项发生了变化、被添加或被删除。这有助于 React 高效地更新虚拟 DOM 和实际 DOM,提高性能。
key
的值应该是列表中每个项的唯一标识符,比如数据库记录的 ID。- 避免使用数组索引作为
key
,除非列表项的顺序永不改变,且列表不会被添加或删除项。
// 避免使用索引作为 key (除非万不得已)
// menuItems.map((item, index) => (
// <MenuItem key={index} name={item.name} price={item.price} />
// ))
条件渲染:
根据条件显示或隐藏组件或元素。
- 使用
if/else
(在函数组件内部):function Greeting({ isLoggedIn }) {if (isLoggedIn) {return <h1>欢迎回来!</h1>;} else {return <h1>请先登录。</h1>;} }
- 使用三元运算符 (
condition ? true : false
): 适合简单的条件渲染。function Greeting({ isLoggedIn }) {return (<h1>{isLoggedIn ? '欢迎回来!' : '请先登录。'}</h1>); }
- 使用逻辑
&&
(如果条件为真则渲染): 适合只需要在条件为真时渲染某个元素。function Status({ isLoading }) {return (<div>{isLoading && <p>正在加载数据...</p>} {/* isLoading 为真时显示加载信息 */}{!isLoading && <p>数据已加载。</p>} {/* isLoading 为假时显示加载完成信息 */}</div>); }
- 使用元素变量: 将条件渲染的结果赋值给一个变量,然后在 JSX 中使用该变量。
function LoginControl({ isLoggedIn, onLoginClick, onLogoutClick }) {let button;if (isLoggedIn) {button = <button onClick={onLogoutClick}>退出</button>;} else {button = <button onClick={onLoginClick}>登录</button>;}return (<div>{button} {/* 使用变量来渲染 */}</div>); }
小例子:渲染菜单列表和显示加载状态
// src/App.jsx (修改)
import React, { useState } from 'react';
import './App.css';
import MenuList from './components/MenuList';function App() {const [isLoading, setIsLoading] = useState(true);const [menuItems, setMenuItems] = useState([]);// 模拟异步获取菜单数据React.useEffect(() => {setTimeout(() => {const fetchedMenuItems = [{ id: 1, name: '宫保鸡丁', price: 38 },{ id: 2, name: '鱼香肉丝', price: 35 },{ id: 3, name: '麻婆豆腐', price: 28 },];setMenuItems(fetchedMenuItems);setIsLoading(false);}, 2000); // 模拟 2 秒加载时间}, []); // 依赖数组为空,只在组件挂载时运行一次return (<div className="App"><h1>我们的特色菜单</h1>{/* 条件渲染:如果正在加载,显示加载信息 */}{isLoading && <p>菜单加载中,请稍候...</p>}{/* 条件渲染:如果加载完成且有菜品,渲染菜单列表 */}{!isLoading && menuItems.length > 0 && (<MenuList menuItems={menuItems} />)}{/* 条件渲染:如果加载完成但没有菜品 */}{!isLoading && menuItems.length === 0 && (<p>暂无菜品可用。</p>)}</div>);
}export default App;
小结: 使用 map
方法和唯一的 key
属性是 React 中渲染列表的标准做法,它帮助 React 高效地更新 UI。条件渲染允许你根据不同的条件灵活地显示或隐藏 UI 元素,常用的方式包括 if/else
、三元运算符和逻辑 &&
。
练习:
- 在你的
my-restaurant-app
项目中,创建一个包含任务对象的数组 (每个对象包含id
,text
,isCompleted
属性)。 - 创建一个新的组件
TaskList.jsx
,接收任务数组作为 Props。 - 在
TaskList
组件中,使用map
方法渲染任务列表,为每个任务显示文本。如果任务isCompleted
为true
,则在文本旁边显示一个“√”标记。确保为每个任务项提供唯一的key
属性。 - 修改你的
MenuItem
组件,接收一个stock
(数字) Props。使用条件渲染,如果stock
小于 5,则在菜品价格旁边显示一个“库存紧张!”的提示。