对于React中key的作用,官方没有给出详细的解读,只提到在List中需要给key赋值来区分每一条记录,http://blog.csdn.net/code_for_free/article/details/50514259里讲解了key的使用场景,
http://taobaofed.org/blog/2016/08/24/react-key/从三方面讲了List组件中key存在的原因和List之外使用key作为trick简化代码逻辑,本文以List中新增元素为例,从List子组件生命周期函数的调用角度分析了可以使用的更新方案及key的作用。
通常认为当 React 元素内包含数量或顺序不确定的子元素时,需要提供 key 属性来定位元素是否已经存在。在实际使用中可以认为 key是一个接口,用来对哪些元素新建,哪些元素删除。
比如现有一个List,每个组件新增时需要用ID向后端发起请求(函数应该放在didmount里),当前id数组的状态是[0,1],如何在原来的基础上变成[2,3,0]呢,可以有以下几种方法:
1,删除原来的数组,再添加3个元素,分别设为2,3,0。不需要使用key来标识元素是否存在,这很明显是低效的,而且这会带来副作用(生命周期里init,didmount,willumount都会调用),,
2,直接在后面添加一个元素,值分别设为2,3,0.没有key,用数组下标,最后一个元素0是新增的,需要调用组件的(init,didmount),didmount里接收的是0并向后端发请求
3,按值查找,对0保持不变,删除1,新增2,3,这符合我们想要的逻辑,但是我们还没有告诉react值是什么,List里可能是一个复杂的组件,所以react提供了一个key,让我们自己设置这个元素什么时候需要重新挂载。
下面看其中一个应用场景
点击界面上的按钮add item,在下面的列表增加一个一条记录,记录挂载时在控制台输出自身的ID,数据的数组是按时间正序,视图按时间逆序显示
import React, { Component } from ‘react‘;
class Item extends Component {
componentDidMount(){
console.log(this.props.text);
}
render(){
return ( <li>{this.props.text}</li>)
}
};
class App extends Component {
constructor (){
super()
this.state={arr:[0,1]};
this.addItem=this.addItem.bind(this)
}
addItem(){
var arr=this.state.arr.slice(0);
arr.push(arr.length);
this.setState({arr:arr});
}
render() {
var arr=this.state.arr.slice(0);
arr.reverse();
return (
<div className="App">
<button onClick={this.addItem}>add item</button>
<ul>
{arr.map((item,index)=>{
return <Item key={index} text={item}/>
})}
</ul>
</div>
);
}
}
export default App;
当APP的render里不设置key 或者key={index} 时,每次新挂载的节点都是0(其他节点能在willreceiveprops中接检测到改变),因为逆序之后,最后一个元素是0,而这个元素的key之前是没有的,所以要新增节点。要实现目标,需要通过在App的render中设置key={arr.length-index}(因为本例的数组简单,设key={item}也可以),告诉react对应的位置不需要重新挂载。
PS:快速新建React程序用create-react-app挺方便的,不用配置就可以使用热更新,使用方法:https://github.com/facebookincubator/create-react-app