React展示前端首先将DOM转换为虚拟DOM,然后再生成页面上的真实DOM,因此当DOM更新时,React会先更新虚拟DOM,然后将新的虚拟DOM与旧的进行对比,如果遇到相同的,页面上对应的DOM就不需要变动,如果遇到不相同的,那么就更新对应页面上的DOM。
这样的好处就是当一个页面内容很多,但是每次只需要更新一点点内容时,React就会有比较好的性能。
虚拟DOM中key的作用:
1) 简单的说:key是虚拟DOM对象的标识,在更新显示时key起着极其重要的作用。、
2) 详细的说:当状态中的数据发生变化时,react会根据新数据生成新的虚拟DOM,随后React进行新虚拟DOM与旧虚拟DOM的diff比较比较规则如下:
a. 旧虚拟DOM中找到了与新虚拟DOM相同的key:
(1). 若虚拟DOM中的内容没变,直接使用之前的真实DOM
(2). 若虚拟DOM中的内容变了,则生成真实DOM,随后替换掉页面中之前的真实DOM
b. 旧虚拟DOM中未找到与新虚拟DOM相同的key,根据数据创建新的真实DOM,随后渲染到网页。
用index作为key可能会引发的问题:
1)若对数据进行:逆序添加、逆序删除等破环顺序操作,会产生没有必要的真实DOM更新 界面效果没问题,单效率低
2) 如果结构中还包含输入类的DOM,会产生错误DOM更新界面有问题
3) 注意!如果不存在对数据逆序添加、逆序删除等破环顺序操作,仅用于渲染列表用于展示,使用index作为key是没有问题的。
1.最好使用每条数据唯一标识作为key,比如id、手机号、身份证号、学号等唯一值。
2.如果确定只是简单的展示数据,用index也是可以的
用个实例来感受一下。
假设这里是逆序添加元素,就会导致一些问题:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<div id="test">div>
<script src="../js/react.development.js">script>
<script src="../js/react-dom.development.js">script>
<script src="../js/babel.min.js">script>
<script src="../js/prop-types.js">script>
<script type="text/babel">
class Person extends React.Component{
state = {
persons:[
{id:1, name:"小张", age:18},
{id:2, name:"小李", age:19},
]
}
add = () => {
const {persons} = this.state;
const p = {id:persons.length+1, name:"小王", age:20}
this.setState({persons:[p,...persons]})
}
render(){
return (
<div>
<h2>展示人员信息</h2>
<button onClick={this.add}>添加一个小王</button>
<h3>使用index(索引值)作为key</h3>
<ul>{
this.state.persons.map((personObj, index) => {
return <li key={index}>{personObj.name}----{personObj.age}<input type="text"/></li>
})
}
</ul>
<hr/>
<hr/>
<h3>使用id(数据唯一标识)作为key</h3>
<ul>{
this.state.persons.map((personObj, index) => {
return <li key={personObj.id}>{personObj.name}----{personObj.age}<input type="text"/></li>
})
}
</ul>
</div>)
}
}
ReactDOM.render(<Person/>, document.getElementById("test"))
script>
body>
html>
运行后

页面文本框输入对应的信息,然后点击按钮

发现逆序添加元素时

用index会导致错位,因为
index原本是 小张0,小李1,现在逆序添加小王,那么现在小王为0,小张1,小李2,导致DOM得重新生成,而输入框的内容并未改变,则保留,就会导致这样的错误。
但是如果顺序添加元素,这个实例其实也没什么问题:
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<div id="test">div>
<script src="../js/react.development.js">script>
<script src="../js/react-dom.development.js">script>
<script src="../js/babel.min.js">script>
<script src="../js/prop-types.js">script>
<script type="text/babel">
class Person extends React.Component{
state = {
persons:[
{id:1, name:"小张", age:18},
{id:2, name:"小李", age:19},
]
}
add = () => {
const {persons} = this.state;
const p = {id:persons.length+1, name:"小王", age:20}
this.setState({persons:[...persons,p]})
}
render(){
return (
<div>
<h2>展示人员信息</h2>
<button onClick={this.add}>添加一个小王</button>
<h3>使用index(索引值)作为key</h3>
<ul>{
this.state.persons.map((personObj, index) => {
return <li key={index}>{personObj.name}----{personObj.age}<input type="text"/></li>
})
}
</ul>
<hr/>
<hr/>
<h3>使用id(数据唯一标识)作为key</h3>
<ul>{
this.state.persons.map((personObj, index) => {
return <li key={personObj.id}>{personObj.name}----{personObj.age}<input type="text"/></li>
})
}
</ul>
</div>)
}
}
ReactDOM.render(<Person/>, document.getElementById("test"))
script>
body>
html>
运行结果:

所有还是需要将key设置为唯一标识,不能简单用index,因为可能到时候会出现bug。