文章首发于github博客react
以前在写react的时候,当咱们作map循环的时候,当咱们没有一个惟一id来标识每一项item的时候,咱们可能会选择使用indexgit
data.map((item, index) => {
return <li key={index}>{item}</li>
})
复制代码
可是其实当你使用index来做为惟一key的时候,实际上是由一个大坑的,什么坑呢?必须坑了你才知道,来看下面的这种状况:github
class App extends React.Component{
constructor(props) {
super(props)
this.state = {
list: [{id: 1,val: 'aa'}, {id: 2, val: 'bb'}, {id: 3, val: 'cc'}]
}
}
click() {
this.state.list.reverse()
this.setState({})
}
splice() {
this.state.list.splice(1,1)
this.setState({})
}
render() {
return (
<ul>
<div onClick={this.splice.bind(this)}>delete</div>
<div onClick={this.click.bind(this)}>reverse</div>
{
this.state.list.map(function(item, index) {
return (
<Li key={index} val={item.val}></Li>
)
}.bind(this))
}
</ul>
)
}
}
class Li extends React.Component{
constructor(props) {
super(props)
}
componentDidMount() {
console.log('===mount===')
}
componentWillUpdate(nextProps, nextState) {
console.log('===update====')
}
render() {
return (
<li>
{this.props.val}
<input type="text"></input>
</li>
)
}
}
复制代码
页面渲染好了以后,3个input输入框依次输入1,2,3: 当咱们用index做为key的时候,点击reverse会发现,input输入框仍是1,2,3顺序显示,可是这并不符合咱们的预期,控制台中此时打印的也是update; 当咱们用对象中的id做为key的时候,点击reverse,此时神奇的事情发生了,input输入框变成了3,2,1,符合咱们的预期,控制台此时打印的也是update;算法
为何会这样呢?bash
当咱们传入index做为key时,此时的key为0,1,2, 当咱们点击reverse从新排序后,index传进去的key仍是0,1,2,此时react比较key=0时,发现只须要更新子节点的值就能够,因而只把item替换成了cc,而input则相反, 当咱们传入id做为index的时候,,点击reverse后,此时的key变成了3,2,1,根据react的diff算法,react仍是能分辨出只须要移动子节点便可完成更新,所以input也随之变化。ui
那说了这么多,其实对于index做为key咱们是不推荐的,除非你可以保证他们不会发生变化。this
参考文献 index as a key is an anti-pattern, 有问题能够在博客下方留言,感谢starspa