为什么ReactJS不为动态子项自动生成密钥?

eln*_*ren 10 javascript reactjs react-jsx

在编写ReactJS时,我必须为动态子项提供密钥.例如:

render() {
  const {options} = this.state
  const availableOptions = options.map(opt => {
    return (
      <option key={opt.id} value={opt.id}>{opt.displayValue}</option>}
    )
  }

  return (
    <select onChange={this._onOptionSelect}>
      {availableOptions}
    </select>
  )
}
Run Code Online (Sandbox Code Playgroud)

我明白为什么他们的钥匙在那里.但为什么必须给他们?无法做出反应只是分配一个正在运行的号码或UUIDv4或其他东西?

相关文档:http://facebook.github.io/react/docs/multiple-components.html#dynamic-children

And*_*ker 6

文艺青年最爱的

您需要为与该元素的数据相关联的动态元素(可能是数据库字段中的id或其他内容)分配唯一键,因为它会停止不必要的重新呈现.这是React的主要吸引力,以及为什么它以其性能着称.

原因

您需要为动态子项分配唯一键,因为这就是React的虚拟DOM将该元素与特定数据相关联的方式.我想一个例子可以帮助说明.

假设您有一个包含1,000个动态生成项目的列表.您可以使用indexmap函数传入的参数来动态地为这些项分配密钥.但是,如果您想更改这些项目的顺序,可能会按字母顺序排序?因为key那些项目不依赖于特定的数据而是仅仅是动态生成,所以React虚拟DOM无法跟踪这些元素.这意味着它必须重新渲染所有 1,000个元素才能改变排序.但是,假设每个项目都分配了一个从数据库中填充的唯一ID.虚拟DOM足够聪明,即使元素的顺序发生了变化,元素本身的数据仍然是相同的.因此,尽管他们的订单已被更改,但它不会重新呈现任何元素.

如果其中任何一个不清楚,一旦你剖析了虚拟DOM的真正工作方式,它就完全有意义了.本质上,虚拟DOM是实际DOM的副本.React比较两者,只重新渲染实际改变的内容.这就是React获得速度的地方.因此,假设您有一个包含3个动态<Item />组件的列表,并且您还可以动态生成其密钥.

<Item key="1">Banana</Item>
<Item key="2">Orange</Item>
<Item key="3">Apple</Item>
Run Code Online (Sandbox Code Playgroud)

现在,如果按字母顺序重新排序这些项目,它们的键也将动态重新分配.

<Item key="1">Apple</Item>
<Item key="2">Banana</Item>
<Item key="3">Orange</Item>
Run Code Online (Sandbox Code Playgroud)

此时,React比较键1的内容,并查看它是否已从上一个键1的渲染更改.它已完全重新呈现该元素.然后它检查键2.它的内容也发生了变化,因此重新渲染.这将继续整个列表.

现在假设每个项目都有一个与数据库中的关联的唯一ID,并将其指定为键.

<Item key="782364">Banana</Item>
<Item key="434533">Orange</Item>
<Item key="834535">Apple</Item>
Run Code Online (Sandbox Code Playgroud)

现在我们按字母顺序重新排序该列表:

<Item key="834535">Apple</Item>
<Item key="782364">Banana</Item>
<Item key="434533">Orange</Item>
Run Code Online (Sandbox Code Playgroud)

此时,React将检查具有键834535的项目的内容是否仍然相同.好了,内容还是一样的!因此,当该元素获得不同的顺序时,它不会被重新渲染.然后,它使用密钥782364检查元素,并发现其内容也相同.这也是整个清单的继续.

虽然在一个小列表中,您可能不会注意到动态生成的密钥与直接与该元素的数据绑定的密钥之间的区别,对于大型列表,性能优势是巨大的.而这确实是React的主要吸引力 - 非常智能的重新渲染.