列表 & Keys
在JavaScript中map()函數(shù)可以對(duì)數(shù)組中的每一項(xiàng)元素進(jìn)行定義操作,比如對(duì)數(shù)組中的元素都翻倍:
const numbers = [1,2,3];
const doubled = numbers.map(number => number * 2);
console.log(doubled);
那么輸出的結(jié)果是[2,4,6];
在React中,可能需要的操作是把數(shù)組轉(zhuǎn)換成數(shù)列元素的過程,可以認(rèn)為是*React元素的數(shù)組。
渲染多個(gè)組件
比如說現(xiàn)在有一個(gè)數(shù)組[1,2,3],可能經(jīng)過渲染后需要的是一個(gè)元素?cái)?shù)組,如多個(gè)<li>1</li>這種,如下:
const numbers = [1,2,3];
const listItems = numbers.map(number => <li>{number}</li>);
ReactDOM.render(
<ul>{listItems}</ul>, document.getElementById('root')
);
如下圖:

基礎(chǔ)列表組件
如果需要渲染這種列表,最好是將列表渲染到一個(gè)組件中,進(jìn)行了組件的抽象。
根據(jù)上邊的例子,其實(shí)就是將數(shù)組轉(zhuǎn)變成列表元素的過程封裝到一個(gè)組件中,組件接受一個(gè)numbers數(shù)組作為參數(shù),最后渲染后輸出一個(gè)列表。如下:
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map(number => <li>{number}</li>);
return <ul>{listItems}</ul>;
}
const numbers = [1,2,3];
ReactDOM.render(
<NumberList numbers={numbers} />, document.getElementById('root')
);
但這樣其實(shí),在返回的列表元素中,每個(gè)元素應(yīng)該指定一個(gè)key,如:
numbers.map(number => <li key="abc">{number}</li>);
key值建議是一個(gè)字符串,并且在這個(gè)列表中是唯一的。
Keys
Keys可以在DOM中的某些元素被增加或者刪除的時(shí)候幫助React識(shí)別哪些元素發(fā)生了變化。在一個(gè)列表中,每個(gè)元素最好擁有唯一的字符串形式的key值。當(dāng)然如果沒有具體的值來作為key值時(shí),可以使用列表元素的序號(hào)索引作為key值。
numbers.map((number,index) => <li key={index.toString()}>{number}</li>);
關(guān)于Keys的深度解讀和算法原理,可以參考深度解析key的必要性。
元素的key只有放在其環(huán)繞數(shù)組的上下文中才有意義。
比如,提取了一個(gè)ListItem組件,那么key應(yīng)該放在<ListItem />這個(gè)元素上,而不是ListItem中的<li>元素上。
- 不正確是使用方式
function ListItem(props) {
const value = props.value;
return (
// 錯(cuò)啦!你不需要在這里指定key:
<li key={value.toString()}>
{value}
</li>
);
}
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
//錯(cuò)啦!元素的key應(yīng)該在這里指定:
<ListItem value={number} />
);
return (
<ul>
{listItems}
</ul>
);
}
const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
<NumberList numbers={numbers} />,
document.getElementById('root')
);
- 正確的使用方式
function ListItem(props) {
// 對(duì)啦!這里不需要指定key:
return <li>{props.value}</li>;
}
function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
// 又對(duì)啦!key應(yīng)該在數(shù)組的上下文中被指定
<ListItem key={number.toString()}
value={number} />
);
return (
<ul>
{listItems}
</ul>
);
}
const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
<NumberList numbers={numbers} />,
document.getElementById('root')
);
一個(gè)好的大拇指法則:元素位于map()方法內(nèi)時(shí)需要設(shè)置鍵屬性。
key的值需要在同一個(gè)列表中也就是兄弟元素之間保持唯一即可,不用全局保持唯一。
不過需要注意的是,key是作為給React提示的,不會(huì)傳遞給組件,也就是使用組件的props對(duì)象是拿不到key值的。如下圖:

可以看到執(zhí)行結(jié)果,冒號(hào)":"后面的值并沒有輸出。
如上圖中的代碼,可以將map()函數(shù)嵌入到JSX語法的大括號(hào){}中。
