一、列表渲染
我们再react中如果渲染列表,一般使用map方法进行渲染
import React from "react";
export default class LearnJSX2 extends React.Component {
state = {
infos: [
{
name: "张三",
age: 18,
},
{
name: "李四",
age: 20,
},
{
name: "王五",
age: 25,
},
],
};
render() {
return (
<div>
<div>
{
/**
* 使用 map进行列表渲染
* map返回要渲染的列表jsx
*
* 使用箭头函数 可以直接return 但是要注意加括号
* 并且 括号内 只能有一个根元素
*/
this.state.infos.map((item, index) => (
// 循环的时候必须要在最上层的元素上加key
<div key={index}>
{item.name} -- {item.age}
</div>
))
}
</div>
</div>
);
}
}
二、为什么map的时候要加key
1、作用
key是react用来追踪哪些列表的元素被修改,被添加或者是被删除的辅助标示。在开发过程中我们需要保证某个元素的key在其同级元素中具有唯一性。
在react的diff算法中react会借助元素的key来判断该元素是最新创建的还是被移动而来的,从而减少不必要的元素渲染。除此之外,react还要根据key来判断元素与本地状态的关联关系。
2、注意
- key的值一定要和具体的元素一一对应
- 尽量不要用数组中的index来作为key的值
- 当我们在做数组遍历批量生成子节点时,切记同层级的每个子节点的key值不能重复且不会发改变,否则将会产生不可预估的bug
- key改变组件会重新渲染
2、为什么index不能作为key呢?
编写一个列表,点击列表中的每一项进行删除
使用index当做key
import React from "react";
export default class LearnJSX3 extends React.Component {
state = {
arr: ["a", "b", "c", "d"],
};
delItem(index) {
this.state.arr.splice(index, 1);
this.setState({
arr: this.state.arr,
});
}
render() {
return (
<div>
<div>
{/*
使用key当做下标
*/}
{this.state.arr.map((item, index) => (
<div onClick={() => this.delItem(index)} key={index}>
{item}
</div>
))}
</div>
</div>
);
}
}
这么乍一看,好像可以正常实现功能,但是我们通过浏览器的控制台检查列表的渲染后发现,我们删除了一个项,竟然连带着整个列表都进行了重新渲染!
使用item或者其它不会改变的项当做key
import React from "react";
export default class LearnJSX3 extends React.Component {
state = {
arr: ["a", "b", "c", "d"],
};
delItem(index) {
this.state.arr.splice(index, 1);
this.setState({
arr: this.state.arr,
});
}
render() {
return (
<div>
<div>
{/*
使用item当做下标
*/}
{this.state.arr.map((item, index) => (
<div onClick={() => this.delItem(index)} key={item}>
{item}
</div>
))}
</div>
</div>
);
}
}
原因
当我们用index做下标的时候,点击删除列表中的每一项,下标都会发生变化,如果用下标当做key就会触发dom重新渲染。如下图所示。
<!-- newVDom -->
<div>
<div>b</div> <!-- key==0 -->
<div>c</div> <!-- key==1 -->
<div>d</div> <!-- key==2 -->
</div>
<!-- oldVDom -->
<div>
<div>a</div> <!-- key==0 -->
<div>b</div> <!-- key==1 -->
<div>c</div> <!-- key==2 -->
<div>d</div> <!-- key==3 -->
</div>
oldVDom -->
<div>
<div>a</div> <!-- key==0 -->
<div>b</div> <!-- key==1 -->
<div>c</div> <!-- key==2 -->
<div>d</div> <!-- key==3 -->
</div>