1.key的作用:
key是虚拟Dom对象的标识,在更新显示时key有重要的作用。
2.当状态中的数据发生变化的时候,react会根据新数据生成新的Dom与旧虚拟Dom的diff比较:
(1) 旧虚拟Dom中找到了与新虚拟Dom相同的key:
若虚拟Dom中内容没变,直接使用之前的真实Dom
若虚拟Dom中内容变了,则生成的真实Dom,随后替换掉页面中之前的真实Dom
(2) 用index作为key可能引发的问题:
若数据进行:逆序添加,逆序删除等破坏顺序操作:会产生没有必要的真实Dom更新。虽然页面效果没有问题,但是效率低。
若结构中包含输入类的Dom : 会产生错误Dom更新,导致界面会有问题
注意:如果不存在对数据的逆序添加,逆序删除等破坏顺序操作,仅用于渲染列表展示,使用index作为key也是可以的。
3.如何选择key值
a. 使用每一条数据的唯一标识2作为key,比如id,手机号,身份证
b. 如果确定只是简单的展示数据,也可以使用index
{
todos.map((todo, index) => (
<Todo {...todo} key={index} />
))
}
key 值是 React 用来判断 DOM 元素的唯一依据。当我们尝试向列表中添加、删除一项数据的时候会发生什么?如果 key 值和之前的相同,React 会假设这是同一个组件。
class Item extends React.Component {
render() {
return (
<div className="form-group">
<label className="col-xs-4 control-label">{this.props.name}</label>
<div className="col-xs-8">
<input type='text' className='form-control' />
</div>
</div>
)
}}
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
list: []
};
}
addItem() {
const id = +new Date;
this.setState({
list: [ {name: 'Baz' + id, id} , ...this.state.list]
});
}
render() {
return (
<div>
<button className='btn btn-primary' onClick={this.addItem.bind(this)}>
添加
</button>
// <h3>错误 <code>key=index</code></h3>
<h3>错误 <code>key=index</code></h3>
<form className="form-horizontal">
{this.state.list.map((todo, index) =>
<Item {...todo} key={index} />
)}
</form>
// <h3>正确 <code>key=id</code></h3>
<h3>正确 <code>key=id</code></h3>
<form className="form-horizontal">
{this.state.list.map((todo) =>
<Item {...todo} key={todo.id} />
)}
</form>
</div>
)}
}
React.render(<Example />, document.getElementById('app'))
先点击添加按钮,在文本框中输入一些测试值。
再点击一次添加按钮,在列表顶部添加一个空的文本框,这时候有发现问题。
由于错误的使用 index 作为 key 值,React 在渲染 list 列表时,假定 key = 0 就是之前添加的第一个文本框,于是错误的将第一次输入的内容渲染到了我们新添加的文本框上。
解决方案:
使用唯一 id 作为 key 值。如果数据项有 id 并且是唯一的,就使用 id 作为 key。如果没有,可以设置一个全局变量来保证 id 的唯一性。
class Example extends React.Component {
this.listCounter = 1
//...
addItem() {
const id = this.listCounter++;
this.setState({
list: [ {name: 'Baz' + id, id} , ...this.state.list]
});
}
render () {
//...
}}
在实际生产环境中,一般使用第三方库来生成唯一 id
const shortid = require('shortid');
// ...
addItem() {
const id = shortid.generate();
this.setState({
list: [ {name: 'Baz' + id, id} , ...this.state.list]
});
}
//...