Javascript 为什么';为动态子对象自动生成密钥?

Javascript 为什么';为动态子对象自动生成密钥?,javascript,reactjs,react-jsx,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 ( <s

在编写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>
  )
}
render(){
const{options}=this.state
const availableOptions=options.map(opt=>{
返回(
{opt.displayValue}
)
}
返回(
{availableOptions}
)
}
我明白他们为什么会在那里。但是为什么我必须给他们?不能只分配一个运行的号码或UUIDv4或其他什么

相关文件:

为什么ReactJS不能为动态子对象自动生成关键点

确实如此,因为它需要一些东西来标识虚拟dom树中的元素。如果您在忽略
键的情况下检查生成的html中的一些动态子项,您将看到:

其中
键∈ {0,1,2,3}

但这是未指明的行为,你应该不要依赖它。 警告之所以存在,是因为:

  • React不想也不想对您的应用程序做出任何假设。开发人员有责任提供合适的密钥,以便应用所有React特定的优化(例如,重用dom节点)
  • 他们(Facebook)可以随时更改未指定的默认行为,从而破坏任何依赖该行为的代码
重复的次数不多:不要依赖默认行为!

Tl;dr 您需要为与该元素的数据相关联的动态元素(可能是数据库字段中的id或其他内容)分配一个唯一键,因为它会停止不必要的重新渲染。这是React的主要特点,也是它以性能著称的原因

理由 您需要为动态子项分配一个唯一的键,因为React是如何将该元素与特定数据段关联的。我认为一个示例将有助于说明这一点

假设您有一个由1000个动态生成的项目组成的列表。您可以使用从
map
函数传入的
index
参数来动态地为这些项目分配一个键。但是,如果您想更改这些项目的顺序,可能会按字母顺序对它们进行排序,因为e项不绑定到特定的数据段,而是动态生成的,React virtual DOM无法跟踪这些元素。这意味着它必须重新呈现所有1000个元素,才能更改排序。但是,假设每个项目都有一个从数据库填充的唯一ide、 虚拟DOM足够聪明,可以看到即使元素的顺序发生了变化,元素本身中的数据仍然是相同的。因此,它不会重新呈现任何元素,尽管它们的顺序发生了变化

如果其中任何一个都不清楚,那么一旦你剖析虚拟DOM的实际工作原理,它就完全有意义了。从本质上说,虚拟DOM是实际DOM的副本。React比较两者,只重新呈现实际更改的内容。这就是React获得其速度的原因。因此,假设你有一个包含3个动态
组件的列表,你也可以动态生成它们的密钥

<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>
香蕉 橙色 苹果
现在,如果您按字母顺序重新排列这些项,它们的键也将被动态重新分配

<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将检查键为834535的项的内容是否仍然相同。好吧,内容仍然相同!因此,虽然该元素获得不同的顺序,但不会重新呈现。然后,它检查键为782364的元素,并发现其内容也相同。这也将继续整个列表


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

您提到“排序”的那一刻所有东西都单击了-当然,这就是为什么它一定是。elnygren,很高兴我能帮你澄清这一点!如果你认为这充分回答了这个问题,你介意接受它以便其他人可以看到吗?你是正确的,但是,如果你不指定与元素数据相关的键,你会得到很多不必要的结果安迪·诺尔克的回答中解释了这一点。