Tl;博士
您需要为与该元素的数据(可能是来自数据库字段的 id 或其他内容)关联的动态元素分配一个唯一键,因为它会阻止不必要的重新渲染。这是 React 的主要吸引力,也是它以性能着称的原因。
原因
您需要为动态子项分配一个唯一键,因为这是 React 的虚拟 DOM将该元素与特定数据相关联的方式。我认为一个例子将有助于说明。
假设您有一个包含 1,000 个动态生成项目的列表。您可以只使用index从map函数传入的参数为这些项目动态分配一个键。但是,如果您想更改这些项目的顺序 - 可能按字母顺序排序怎么办?因为key这些项目上的 不依赖于特定的数据,而是动态生成的,所以 React 虚拟 DOM 无法跟踪这些元素。这意味着它必须重新渲染所有1,000 个元素只是为了改变排序。但是,假设这些项目中的每一个都有一个分配给它的唯一 ID,该 ID 是从数据库填充的。虚拟 DOM 足够聪明,可以看到即使元素的顺序发生了变化,元素本身的数据仍然相同。因此,它不会重新渲染任何元素,尽管它们的顺序已更改。
如果其中任何一个不清楚,那么一旦您剖析了虚拟 DOM 的真正工作原理,就完全可以理解了。本质上,虚拟 DOM 是实际 DOM 的副本。React 比较两者,只重新渲染实际更改的内容。这就是 React 获得速度的地方。因此,假设您有一个包含 3 个动态<Item />组件的列表,并且您也在动态生成它们的密钥。
<Item key="1">Banana</Item>
<Item key="2">Orange</Item>
<Item key="3">Apple</Item>
现在,如果您按字母顺序对这些项目重新排序,它们的键也将动态重新分配。
<Item key="1">Apple</Item>
<Item key="2">Banana</Item>
<Item key="3">Orange</Item>
在这一点上,React 比较键 1 的内容,看看它是否与键 1 的先前渲染相比发生了变化。因此它完全重新渲染了该元素。然后它检查键 2。它的内容也发生了变化,所以它被重新渲染。这对整个列表继续。
现在假设每个项目在数据库中都有一个与其关联的唯一 ID,您将其指定为键。
<Item key="782364">Banana</Item>
<Item key="434533">Orange</Item>
<Item key="834535">Apple</Item>
现在我们按字母顺序重新排列该列表:
<Item key="834535">Apple</Item>
<Item key="782364">Banana</Item>
<Item key="434533">Orange</Item>
此时 React 会检查 key 为 834535 的项目的内容是否仍然相同。好了,内容都还是一样的!因此,虽然该元素获得不同的顺序,但不会重新渲染。然后检查key为782364的元素,发现它的内容也是一样的。这也适用于整个列表。
虽然在一个小列表中,您可能不会注意到动态生成的密钥与直接绑定到该元素数据的密钥之间的区别,对于大型列表,性能优势是巨大的。这确实是 React 的主要吸引力——非常智能的重新渲染。