首先,让我们看下在 Javascript 中如何转化列表。
如下代码,我们使用 map() 函数让数组中的每一项变双倍,然后我们得到了一个新的列表 doubled 并打印出来:
![fa253727fae30d64767d74b498c1725c.png](https://i-blog.csdnimg.cn/blog_migrate/51edda26da86e9bf59afe76055be8be3.jpeg)
代码打印出 [2, 4, 6, 8, 10]。
在 React 中,把数组转化为元素列表的过程是相似的。
渲染多个组件
你可以通过使用 {} 在 JSX 内构建一个元素集合。
下面,我们使用 Javascript 中的 map() 方法来遍历 numbers 数组。将数组中的每个元素变成
标签,最后我们将得到的数组赋值给 listItems:![73bc13b55027c28dc6c3c60882ee97cd.png](https://i-blog.csdnimg.cn/blog_migrate/5448f60869e7f2258c28e15084ba4ce3.jpeg)
我们把整个 listItems 插入到
- 元素中,然后渲染进 DOM:
![69fcb2a6a179e10344435e33372c5482.png](https://i-blog.csdnimg.cn/blog_migrate/d6890021ab1b8b11a83b58f419a2c0ed.jpeg)
基础列表组件
通常你需要在一个组件中渲染列表。
我们可以把前面的例子重构成一个组件,这个组件接收 numbers 数组作为参数并输出一个元素列表。
![7e01edcd9f0c28aa9c42f8b708c81c1d.png](https://i-blog.csdnimg.cn/blog_migrate/62dd7e2331c2a6ae9e506564e08b2ca6.jpeg)
当我们运行这段代码,将会看到一个警告 a key should be provided for list items,意思是当你创建一个元素时,必须包括一个特殊的 key 属性。我们将在下一节讨论这是为什么。
让我们来给每个列表元素分配一个 key 属性来解决上面的那个警告:
![97864cccd7d84c436c35761e42a7a6dc.png](https://i-blog.csdnimg.cn/blog_migrate/160858027e0181eb23d6ad9ea177ce39.jpeg)
key
key 帮助 React 识别哪些元素改变了,比如被添加或删除。因此你应当给数组中的每一个元素赋予一个确定的标识。
![c057f7c8a39017ede827765b5abc7272.png](https://i-blog.csdnimg.cn/blog_migrate/1fe18966b6e4bfe6a3c2d941ff18fc5d.jpeg)
一个元素的 key 最好是这个元素在列表中拥有的一个独一无二的字符串。通常,我们使用数据中的 id 来作为元素的 key:
![88e03cfa11ea22f575021ab5712a5741.png](https://i-blog.csdnimg.cn/blog_migrate/ce0e3d1f18533c60d033aae12b1e78b9.jpeg)
当元素没有确定 id 的时候,万不得已你可以使用元素索引 index 作为 key:
![2db2aee88cade2b8470a76e2849865fe.png](https://i-blog.csdnimg.cn/blog_migrate/acd702df17eb0a3044e072c25d006bca.jpeg)
如果列表项目的顺序可能会变化,我们不建议使用索引来用作 key 值,因为这样做会导致性能变差,还可能引起组件状态的问题。可以看看 Robin Pokorny 的深度解析使用索引作为 key 的负面影响这一篇文章。如果你选择不指定显式的 key 值,那么 React 将默认使用索引用作为列表项目的 key 值。
要是你有兴趣了解更多的话,这里有一篇文章深入解析为什么 key 是必须的可以参考。
用 key 提取组件
元素的 key 只有放在就近的数组上下文中才有意义。
比方说,如果你提取出一个 ListItem 组件,你应该把 key 保留在数组中的这个 元素上,而不是放在 ListItem 组件中的
元素上。例子:不正确的使用 key 的方式
![26fd751daacfb454696aa4dfc081a1ab.png](https://i-blog.csdnimg.cn/blog_migrate/f19ec03641b2aa6b72b9aa8839e1d679.jpeg)
例子:正确的使用 key 的方式
![43ca6f23d5f3833e39b53c3e180d2155.png](https://i-blog.csdnimg.cn/blog_migrate/ac33ec633aa75dacfb79a0af71d6558c.jpeg)
一个好的经验法则是:在 map() 方法中的元素需要设置 key 属性。
key 只是在兄弟节点之间必须唯一
数组元素中使用的 key 在其兄弟节点之间应该是独一无二的。然而,它们不需要是全局唯一的。当我们生成两个不同的数组时,我们可以使用相同的 key 值:
![285fa7fe42c2ee6253fdc74754c3542d.png](https://i-blog.csdnimg.cn/blog_migrate/9d816558d94c5fd499fc422869d0518f.jpeg)
key 会传递信息给 React ,但不会传递给你的组件。如果你的组件中需要使用 key 属性的值,请用其他属性名显式传递这个值:
![7157b85ad1c88a6707a7770baec30c9b.png](https://i-blog.csdnimg.cn/blog_migrate/5cc7ad09862d26062eb9a0c00319e63d.jpeg)
上面例子中,Post 组件可以读出 props.id,但是不能读出 props.key。
在 JSX 中嵌入 map()
在上面的例子中,我们声明了一个单独的 listItems 变量并将其包含在 JSX 中:
![9078213f4f1b9d883b6bbc40cab426c3.png](https://i-blog.csdnimg.cn/blog_migrate/e7b9d136de5ff6fab124d70043070314.jpeg)
JSX 允许在大括号中嵌入任何表达式,所以我们可以内联 map() 返回的结果:
![2b9ab2427b0f8c9875aa3e8708265b20.png](https://i-blog.csdnimg.cn/blog_migrate/259c85085b33c06c518ec374bfcffa9c.jpeg)
这么做有时可以使你的代码更清晰,但有时这种风格也会被滥用。就像在 JavaScript 中一样,何时需要为了可读性提取出一个变量,这完全取决于你。但请记住,如果一个 map() 嵌套了太多层级,那可能就是你提取组件的一个好时机。