首先,讓咱們回顧一下如何在JavaScript中遍歷lists。javascript
下面的代碼,咱們使用map()
函數獲取一個數字
數組,並將它們的值加倍。 咱們將map()
返回的新數組賦給變量doubled
並記錄下來:java
const numbers = [1, 2, 3, 4, 5]; const doubled = numbers.map(item => item * 2); console.log(doubled); //=> [2, 4, 6, 8, 10]
上面的代碼會在控制檯打印[2, 4, 6, 8, 10]
。
在React中,將數組轉換爲元素集合
幾乎和上面的代碼是同樣的。react
您能夠本身一個建立元素集合,並使用花括號{}
將它們包含在JSX中。
下面,咱們使用Javascript map()
函數循環一個數字數組。 咱們爲每一個item
返回一個<li>
元素。 最後,咱們將結果數組的元素賦給listItems
:數組
const numbers = [1, 2, 3, 4, 5]; const listItems = numbers.map(item => <li>{item}</li>);
咱們將整個listItems
數組包含在<ul>
元素中,並將其渲染到DOM:dom
ReactDOM.render( <ul>{listItems}</ul>, document.getElementById('root') )
此代碼將會顯示1到5之間的數字。ide
一般你會將List放在組件中。
咱們能夠將前面的例子重構爲接受數字數組的組件,並輸出一個無序的元素列表。函數
import React from 'react'; import ReactDOM from 'react-dom'; function NumberList(props) { const numbers = props.numbers; const listItems = numbers.map(item => <li>{item}</li>); return ( <ul>{listItems}</ul> ); } const numbers = [1, 2, 3, 4, 5]; ReactDOM.render( <NumberList numbers={numbers} />, document.getElementById('root') );
當您運行此代碼時,將會收到一條警告,
Each child in an array or iterator should have a unique "key" prop. Check the render method of "NumberList".
post
提示指出應該爲列表的每一項提供一個屬性key
。 「key」
是建立元素列表時須要包含的特殊字符串屬性。 咱們將在下一節討論爲何它很重要。code
讓咱們給numbers.map()
的列表項分配一個key
,並修復那個提示缺乏key
的問題。排序
import React from 'react'; import ReactDOM from 'react-dom'; function NumberList(props) { const numbers = props.numbers; - const listItems = numbers.map(item => <li>{item}</li>); + const listItems = numbers.map(item => <li key={item.toString()}>{item}</li>); return ( <ul>{listItems}</ul> ); } const numbers = [1, 2, 3, 4, 5]; ReactDOM.render( <NumberList numbers={numbers}/>, document.getElementById('root') )
keys
幫助肯定哪些item
已更改,已添加或已刪除。 應該給數組中的元素設置上key
屬性,以便給元素一個穩定的身份:
const numbers =[1, 2, 3, 4, 5]; const listItems = numbers.map(item => <li key={item.toString()}> {item} </li> );
最好的方法是使用一個字符串
來選擇key
,它是其兄弟之間一個列表項的惟一標識
。 一般,您會使用數據中的ID做爲key:
const todoItems = todos.map(todo => <li key={todo.id}> {todo.text} </li> );
當您對已渲染的item沒有穩定的ID時,您能夠將項目index用做關鍵字:
const todoItems = todos.map((todo, index) => // 若是todo沒有一個穩定的id,可使用這種方法 <li key={index}> {todo} </li> );
若是項目須要實現從新排序,咱們不建議爲key使用索引,由於這將很慢。
Keys僅在循環時的上下文中有意義。
例如,若是您提取了一個ListItem
組件,則應該將該key保存在數組中的<ListItem />
元素上,而不是ListItem
自己的根<li>
元素上。
示例:key的錯誤用法
function ListItem(props) { const value = props.value; return ( <li key={value.toString()}> {value} </li> ); } function NumberList(props) { const numbers = props.numbers; const listItems = numbers.map(item => // 這是錯誤的,這裏應該設置上key <ListItem value={item} /> ); return ( <ul>{listItems}</ul> ); } const numbers = [1, 2, 3, 4, 5]; ReactDOM.render( <NumberList numbers={numbers}> />, document.getElementById('root') )
實例:key的正確用法
function ListItem(props) { // 這纔是正確的,在這裏不須要設置key return <li>{props.value}</li>; } function NumberList(props) { const numbers = props.numbers; const listItems = numbers.map(item => // 這纔是正確的,在這裏設置key <ListItem key={item.toString()} value={item} /> ); return ( <ul> {listItems} </ul> ); } const numbers = [1, 2, 3, 4, 5]; ReactDOM.render( <NumberList numbers={numbers} />, document.getElementById('root') )
注意:map()
中的元素都須要屬性key。在哪兒循環就在哪兒設置key。
數組中使用的key
在其兄弟組件之間應該是惟一的。 可是,它們不須要是全局惟一的。 當咱們生成兩個不一樣的數組時,咱們可使用相同的鍵:
function Blog(props) { const sidebar = ( <ul> {props.posts.map(post => <li key={post.id}> {post.title} </li> )} </ul> ); const content = props.posts.map(post => <div key={post.id}> <h3>{post.title}</h3> <p>{post.content}</p> </div> ); return ( <div> {sidebar} <hr /> {content} </div> ); } const posts = [ {id: 1, title: 'hello zhangyatao', content: 'you\'re so handsome!'}, {id: 2, title: 'hi jiangyanyun', content: 'you\'re so beautiful!'} ]; ReactDOM.render( <Blog posts={posts} />, document.getElementById('root') )
key用來做爲React的觀察點,但它們不會傳遞給您的組件。 若是你須要在組件中使用相同的值,則使用不一樣的名稱顯式地將它做爲props傳遞:
const content = posts.map(post => <Post key={post.id} id={post.id} title={post.title} /> );
使用上面的示例,Post組件能夠讀取props.id
,但不能讀取props.key
。
在上面的示例中,咱們聲明瞭一個單獨的listItems
變量並將其包含在JSX中:
function NumberList(props) { const numbers = props.numbers; const listItems = numbers.map(item => <ListItem key={item.toString()} value={item} /> ); return ( <ul>{listItems}</ul> ); }
JSX容許在大括號中嵌入任何表達式,因此咱們能夠內聯map()
結果:
function NumberList(props) { const numbers = props.numbers; return ( <ul> {numbers.map(item => <ListItem key={item.toString()} value={item} /> )} </ul> ); }
這會讓咱們的代碼更清晰,這種風格能夠被隨意使用。
就像在JavaScript中,它是由你決定是否值得提取一個變量的可讀性。
請記住,若是map()
主體嵌套太多層,那麼它是抽出一個組件的好時機。