React动态渲染:如何用map循环渲染一个列表(List)
React动态渲染:如何用map循环渲染一个列表(List)?
系列回顾:
在上一篇中,我们学习了如何通过onClick
等事件处理,让React应用响应用户的操作。现在我们的组件已经能“听懂话”了。但是,目前为止我们展示的内容都是写死的。如果我们要展示一个从服务器获取的朋友列表,或者一个包含100件商品的清单,总不能在代码里一个一个地手写<li>
标签吧?
欢迎来到React学习的第五站!
今天,我们要学习一个非常实用且强大的技能:如何根据一组数据(通常是一个数组),动态地渲染出一个列表。 这项技能将让你能够构建出内容丰富的、由数据驱动的Web应用。
我们将要使用的核心工具,是JavaScript中一个非常强大的数组方法:.map()
。
核心思想:数据与UI的映射
在React中,我们不直接操作DOM。我们的思维方式是:
有一份数据(数组),就应该对应地生成一份UI(一组组件或元素)。
.map()
方法就是实现这种“映射”关系的不二之P。它会遍历数组中的每一个元素,对每个元素执行你指定的操作,然后返回一个包含所有操作结果的新数组。
在React中,这个“操作”通常就是:把一个数据项,转换成一个JSX元素(比如<li>
)。
实战一:渲染一个简单的水果列表
让我们从一个简单的例子开始,我们有一个包含水果名称的数组,目标是把它们渲染成一个无序列表(<ul>
)。
第一步:准备 App.jsx
和数据
清空 src/App.jsx
,并写入以下代码。我们先在组件内部定义一个水果数组作为我们的数据源。
import './App.css';function App() {const fruits = ['苹果 🍎', '香蕉 🍌', '橙子 🍊', '草莓 🍓'];return (<div><h1>我的水果清单</h1><ul>{/* 我们将在这里动态渲染列表 */}</ul></div>);
}export default App;
第二步:使用 .map()
遍历数组并生成JSX
现在,我们在 <ul>
标签内部,使用花括号 {}
来嵌入JavaScript表达式。这个表达式就是我们的 .map()
操作。
修改return
部分的代码:
function App() {const fruits = ['苹果 🍎', '香蕉 🍌', '橙子 🍊', '草莓 🍓'];return (<div><h1>我的水果清单</h1><ul>{fruits.map((fruit, index) => {return <li key={index}>{fruit}</li>;})}</ul></div>);
}
代码解释:
{...}
: 我们在JSX中打开了一个JavaScript代码块。fruits.map(...)
: 我们调用了fruits
数组的map
方法。(fruit, index) => { ... }
: 这是一个箭头函数,它会被map
方法在遍历数组时,对每个元素都调用一次。fruit
: 代表当前正在被遍历的元素(比如第一次是 ‘苹果 🍎’)。index
: 代表当前元素的索引(从0开始)。
return <li key={index}>{fruit}</li>;
: 这是最关键的一步。对于每一个fruit
,我们都返回一个<li>
JSX元素。{fruit}
会把水果的名称显示出来。最终,map
方法会返回一个由所有这些<li>
元素组成的新数组,React会把这个数组渲染到DOM上。
第三步:查看效果
保存文件,回到浏览器。你会看到一个漂亮的水果列表已经整整齐齐地显示出来了!我们只写了几行代码,就动态地生成了整个列表。
深入理解:key
属性到底是什么?为什么它如此重要?
你可能已经注意到了,我们在<li>
元素上添加了一个key={index}
的属性。如果你不加这个key
,程序虽然能运行,但浏览器控制台会给你一个红色的警告:Warning: Each child in a list should have a unique "key" prop.
key
是React用来识别列表中每个元素的“身份证”。
当列表的数据发生变化时(比如添加、删除或重新排序),React需要一种高效的方式来找出哪些元素是新增的、哪些是删除了、哪些只是移动了位置,从而只对变化的部分进行最小化的DOM更新,而不是重新渲染整个列表。
key
就是React进行这种“对比”的依据。
使用key
的两个重要原则:
key
在兄弟元素之间必须是唯一的。 就像一个班级里,每个学生的学号都不能重复。key
应该保持稳定。 它不应该随着项目的重新渲染而改变。
为什么不推荐使用索引(index)作为key
?
在上面的例子中,我们使用了index
作为key
。对于一个不会改变顺序、不会被删除或插入的静态列表,这是可以接受的。
但是,如果你的列表会发生变化,使用index
作为key
可能会导致严重的性能问题和一些奇怪的bug。想象一下,你删除了数组的第一个元素,原来索引为1的元素现在变成了索引为0,索引为2的变成了1…所有元素的key
都变了!React会认为你修改了列表中的每一个元素,而不是只删除了一个。
最佳实践:使用数据中独一无二的ID作为key
。
实战二:渲染一个包含对象的列表(最佳实践)
在真实世界中,我们的数据通常是对象的数组,每个对象都有一个唯一的id
。
让我们修改一下案例,数据变成一个用户列表。
import './App.css';function App() {const users = [{ id: 1, name: '张三', age: 25 },{ id: 2, name: '李四', age: 30 },{ id: 3, name: '王五', age: 22 }];return (<div><h1>用户列表</h1><ul>{users.map(user => (// 使用每个用户的 id 作为 key<li key={user.id}>姓名: {user.name}, 年龄: {user.age}</li>))}</ul></div>);
}export default App;
代码解释:
- 我们的数据源
users
现在是一个对象数组。 - 在
.map()
中,我们直接使用user.id
作为key
。因为id
是每个用户独有的,并且不会改变,所以这是最理想、最稳健的key
。 - 我们还稍微简化了箭头函数,当函数体只有一行
return
语句时,可以省略{}
和return
关键字。
总结与思考
今天,我们解锁了React中一项至关重要的技能——动态渲染列表。你现在已经能够将任何数组数据转换成漂亮的UI界面了。核心知识点回顾:
- 核心工具: JavaScript的**
.map()
**数组方法。 - 核心思想: 将数据数组映射为UI元素数组。
key
属性: 它是React识别列表项的“身份证”,在兄弟节点间必须是唯一且稳定的。- 最佳实践: 优先使用数据本身提供的唯一ID作为
key
。
我们已经能根据数据批量生成UI了。但有时候,我们并不想显示所有内容,而是想根据某些条件来决定某个UI部分是否应该显示。例如,用户登录后才显示“欢迎信息”,或者数据正在加载时显示“加载中…”。
在下一篇文章 《React条件渲染:如何根据不同条件显示或隐藏一个组件?》 中,我们将学习如何控制UI的显示和隐藏逻辑,让我们的应用更加智能。我们下期再会!