有没有办法让React为孩子们自动定义"钥匙"?

wle*_*300 14 reactjs

我正在学习React,我偶然发现了这个"充满活力的孩子"的怪癖.

带有代码示例的序言:

// Render Pass 1
<Card>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
</Card>

// Render Pass 2
<Card>
  <p>Paragraph 2</p>
</Card>
Run Code Online (Sandbox Code Playgroud)

在第二render()遍中,似乎vdom diffing的工作方式是删除第二个孩子,然后将第一个孩子的文本转换为"第2段".这很快,但如果你需要国家坚持说......第二个孩子,你会发现奇怪的事情发生了!

所以React建议对这些标签使用"key"属性.现在,vdom差异将是惊喜的,你会看到状态得到保留renders().

我的问题:有没有办法让React自己设置"密钥"而不是按照他们建议的方式进行操作?

hop*_*per 19

不,那里没有.

如果没有指定密钥,React的默认行为是使用一种简单的方法来就地更新组件,如您所观察到的那样.在功能上,这相当于根据元素的索引相对于其兄弟指定默认键.在您的示例中,这将看起来像:

// Render Pass 1
<Card>
  <p key={0}>Paragraph 1</p>
  <p key={1}>Paragraph 2</p>
</Card>

// Render Pass 2
<Card>
  <p key={0}>Paragraph 2</p>
</Card>
Run Code Online (Sandbox Code Playgroud)

这就是为什么你看到第一个元素的文本被转换的原因,但是你注意到这并不总是最佳结果.那么为什么React不能使用更智能的自动密钥呢?答案是,为了做到这一点,实际上只有两个选择,两者都不理想:

  1. 他们可以对您的应用程序结构做出某些假设.在您的简短示例中,对于人类来说,段落应该根据其文本内容进行匹配是显而易见的.但是在所有情况下都不一定如此,并且很难将这种逻辑扩展到更复杂的场景,包括自定义元素,大量道具,嵌套子元素等.

  2. 他们可以使用一种奇特的通用差异算法,但就性能而言,这些算法非常昂贵,而React非常认真.关于和解的React 文档说:

    有许多算法试图找到转换元素列表的最小操作集.Levenshtein距离可以在O(n 2)中使用单个元素插入,删除和替换找到最小值.即使我们使用Levenshtein,这也不会发现节点何时移动到另一个位置并且算法要复杂得多.

因此,无论哪种方式,"自动键分配"的任何好处都带来一系列缺点.最后,它并不值得,特别是考虑到在大多数情况下手动分配键并不是那么困难或麻烦.从同一文档页面进一步向下:

在实践中,找到钥匙并不是很难.大多数情况下,您要显示的元素已经具有唯一ID.如果不是这种情况,您可以向模型添加新的ID属性,或者对内容的某些部分进行哈希以生成密钥.请记住,密钥只能在其兄弟姐妹中独一无二,而不是全球唯一.