Javascript 为什么提供key={index}会导致与不定义key不同的行为?

Javascript 为什么提供key={index}会导致与不定义key不同的行为?,javascript,reactjs,ecmascript-6,Javascript,Reactjs,Ecmascript 6,如果我们定义key={index},事情就可以进行,如果我们排除它,事情就不可以进行,但是我希望基于文档的行为是相同的 : 如果您选择不为列表项分配显式键,则React将默认使用索引作为键 为什么会这样?不提供key不应该等同于提供key={index}吗?文档措词不当:如果不指定一个,则作出反应,并且省略key属性与使用key={index}不同。相反,如果不存在键属性,React将基于虚拟DOM父元素的子索引进行内部检查。这些可能并且经常会与您的迭代索引相同,但肯定不总是相同的,依赖它们会导

如果我们定义key={index},事情就可以进行,如果我们排除它,事情就不可以进行,但是我希望基于文档的行为是相同的

:

如果您选择不为列表项分配显式键,则React将默认使用索引作为键


为什么会这样?不提供key不应该等同于提供key={index}吗?

文档措词不当:如果不指定一个,则作出反应,并且省略key属性与使用key={index}不同。相反,如果不存在键属性,React将基于虚拟DOM父元素的子索引进行内部检查。这些可能并且经常会与您的迭代索引相同,但肯定不总是相同的,依赖它们会导致错误

例如,当迭代索引和虚拟DOM子索引不相同时,让我们看看从多个输入列表创建子元素的情况。如果我们不指定键属性,React将警告缺少键,但一切都将按预期工作:

class App extends Component {
  constructor(props) {
    super(props);  
    this.state = {
      a: [1,2,3],
      b: [4,5,6]
   };
  }
  render() {
    const { a, b } = this.state;
    return <div>{
      a.map(e => <p>{e}</p>).concat(b.map(e => <p>{e}</p>))
    }div>;
  }
}
class App extends Component {
  constructor(props) {
    super(props);  
    this.state = {
      a: [1,2,3],
      b: [4,5,6]
   };
  }
  render() {
    const { a, b } = this.state;
    return <div>{
      a.map((e,index) => <p key={index}>{e}</p>)
       .concat(b.map((e, index) => <p key={index}>{e}</p>))
    }div>;
  }
}
这将显示内容为1到3的三个段落,因为这两个数组映射生成的元素既有键,也有键冲突。由于b中的所有元素都有与a中的元素冲突的键,React会将它们扔掉,现在您需要查找一个bug

当然,如果你写的是正确的反应,这不是你通常会遇到的情况。始终使用键,并始终确保它们唯一地标识要映射的元素


这就是说,我已经提交了文件,希望能够更新该文本,以明确该文本不是指代码正在运行的任何迭代的索引,而是它自己的内部子节点索引。

如果从链接向下滚动一点,这里有一个链接,可以提供行为差异的最小可复制示例吗?React根据省略键时需要构建的虚拟DOM使用其自己的内部索引。另外,永远不要使用迭代索引作为键,而是使用该元素的实际唯一值作为键。关键点在于,键唯一地标识了一组元素中的元素,以便React能够正确地完成其工作。这在很大程度上不是良好工作的定义。反应浪费时间不断拆卸和重建相同的数据会浪费cpu时间、时钟时间、内存、不必要地消耗移动设备上的电池等,因此根本无法正常工作。它起作用了,但效果不好,而且肯定不是你应该如何使用React。你之所以受到如此强烈的反对,是因为你的问题没有遵循以下一般形式:解释你在做什么,你对文档链接的期望是什么:这是一个好的链接,你得到了什么。好吧,在4个人引用文档说它不好,6个人投了反对票之后,我仍然很好奇:如果没有关键,你会做出什么反应?老实说,我不知道,我希望看到这个问题的真实答案。这个答案是错误的。如果指定或未指定索引,则元素的路径完全相同。但肯定不总是什么让你这么想?关键是,当没有钥匙时,你会做出什么反应。文档声明,它将把数组中元素的索引作为最终的子数组,而不是将要连接的中间数组。你的例子可能是OP做错了什么,但不是在人们声称文档是错的之前辩论的内容,我实际上在考虑否决这个问题,因为我认为它只是陈述了一些错误的东西,没有一个可复制的例子。人们努力解释,为什么键经常是必要的,虽然这很好,但它是OT。除了最后的子数组显然一点也不明显。到了一定程度,可能值得有人提交一个文档问题,这样React人员就可以明确地说明这一点,而不是让人们猜测它在谈论哪个索引。好吧,是的,只有当你通过设置碰撞键来撒谎以作出反应时,这才是错误的。用一个简单的arr.mapel,i=>{el}你不,当然不是,如果你能用一个映射创建这个场景,这个问题早在React还是零点小的时候就出现了。因此,从字面上引述我自己的回答:这些可能并且经常会与您的迭代索引相同,但肯定不总是如此,因为React不使用迭代代码固有的索引,而是使用其虚拟dom中虚拟元素的子索引。与文本所暗示的不同,当你知道足够多的英语来阅读文档,但还没有足够的React来了解React人对这些词的意思。