key={i}和key={' foo-${i} '}有什么区别吗?



我在读一本高级React书React Cookbook。出于某种原因,作者使用了带有前缀的key,如下所示:

<div>
{state.items.map((s, i) => (
<div key={`square-${i}`}>
{s}
</div>
))}
</div>

我一直看到这样构建key,它总是让我感到惊讶,特别是来自一个高级作者。据我所知,这和仅仅是key={i}没有区别。

当我开始使用React时,我有一些不太高级的React开发人员告诉我,这在嵌套列表时很有用,像这样:

<div>
{state.items.map((s, i) => (
<div key={`square-${i}`}>
{s.map(f, j) => (
<div key={`foo-${j}`}>
{f}
</div>
)}
</div>
))}
</div>

但是,这也是无用的,因为键的唯一性是有作用域的,对吗?因此,不同级别或不同列表中的键不需要是唯一的。

如果我的列表包含两种或两种以上的内容,那么这样做可能会有一些意义,就像这样:

<div key={`${item.type}-${i}`}>

但除此之外,为什么有人会使用基于索引的键来表示索引的形状呢?

我相信人们开始添加前缀是因为他们错误地假设了树的唯一性是如何工作的:

键的作用域是同级的。你可以在组件树上/下使用相同的键,但不能在旁边使用。不过要注意,这与DOM树本身没有直接关系,而是与react组件树有关。

数组类型的react子节点有一个"parent"因此,键可以在"兄弟姐妹"之间重复使用。(从技术上讲,它们不是兄弟,因为它们有这个"数组父元素",这在DOM树中是透明的)。

下面的代码是有效的,不会触发任何警告。相关的react-dom代码可以在这里找到。

<parent key="unique">
<sibling key="must" />
<sibling key="be" />
<sibling key="unique">
<child key="unique" />
</sibling>
</parent>
<div>
{['a', 'b', 'c', 'd', 'e'].map((letter, idx) => (
<span key={idx}>{letter}</span>
))}
{['a', 'b', 'c', 'd', 'e'].map((letter, idx) => (
<span key={idx}>{letter}</span>
))}
</div>

如果数据是"静态的",那么使用索引作为键的方法是非常好的和安全的。并且永远不会改变,否则你可能会有渲染问题和/或性能下降。

使用foo-${i}代替i是多余的,并且行为相同。

因为,索引不推荐用于关键道具,无论它们是单独使用还是在字符串插值中使用。

虽然前缀不变,但index将在数组中添加或删除项目时发生变化,并且foo-0不等于foo-1。在这种情况下,react将重新渲染项目,因为之前的键道具与新的不匹配。

如果列表数据顺序可能改变,react官方文档不建议对键使用索引。我认为作者知道这一点,并为关键字创建前缀,所以它成为字符串,而不仅仅是数字。查看文档的关键

最新更新