react文檔——列表和鍵

列表和鍵

首先,讓我們先回顧一下在 JavaScript 中如何改變列表。

在下面給出的代碼中,我們對numbers數(shù)組調(diào)用map()函數(shù)使它們的值變成雙倍。我們把通過map()返回的新數(shù)組賦值給變量doubled并打印它。

const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map((number) => number * 2);
console.log(doubled);

這段代碼在控制臺打印[2, 4, 6, 8, 10]。

在 React 中,將數(shù)組轉(zhuǎn)換成元素列表的方法幾乎相同。

渲染多個(gè)組件

你可以構(gòu)建元素的集合并使用大括號{}把它們插入到 JSX 中。

下面,我們通過對numbers數(shù)組調(diào)用map()函數(shù)進(jìn)行迭代。我們對每一項(xiàng)返回一個(gè)li元素。最后,我們把元素?cái)?shù)組的結(jié)果賦值給listItems

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
  <li>{number}</li>
);

我們把全部的listItems數(shù)組包裹在一個(gè)ul元素中并渲染到 DOM。

ReactDOM.render(
  <ul>{listItems}</ul>,
  document.getElementById('root')
);

CodePen上試試。

這段代碼顯示從numbers迭代出來 1 到 5 之間的列表。

基礎(chǔ)的列表組件

通常你會在一個(gè)組件內(nèi)部渲染列表。

我們將之前的例子重構(gòu)為一個(gè)組件,使其接收一個(gè)numbers數(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, 4, 5];
ReactDOM.render(
  <NumberList numbers={numbers} />,
  document.getElementById('root')
);

當(dāng)你運(yùn)行這段代碼時(shí),你會得到一個(gè)警告:應(yīng)該為列表項(xiàng)提供一個(gè) key?!発ey”是一個(gè)特殊的字符串屬性,當(dāng)你創(chuàng)建一個(gè)元素列表時(shí),你需要包含它。我們會在接下來的部分討論問什么它這么重要。

讓我們給numbers.map()內(nèi)部的列表項(xiàng)分配一個(gè)key來修復(fù)缺少 key 的問題。

function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    <li key={number.toString()}>
      {number}
    </li>
  );
  return (
    <ul>{listItems}</ul>
  );
}

const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
  <NumberList numbers={numbers} />,
  document.getElementById('root')
);

CodePen上試試。

鍵幫助 React 識別哪個(gè)項(xiàng)發(fā)生了改變,被添加還是被移除。鍵應(yīng)該被賦予數(shù)組內(nèi)部的元素,以給元素一個(gè)固定的標(biāo)識:

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
  <li key={number.toString()}>
    {number}
  </li>
);

選擇一個(gè) key 的最好的方式是使用一個(gè)在兄弟姐妹之間唯一標(biāo)識一個(gè)列表項(xiàng)的字符串。很多時(shí)候你可能會從你的數(shù)據(jù)中使用 IDs 作為鍵:

const todoItems = todos.map((todo) =>
  <li key={todo.id}>
    {todo.text}
  </li>
);

當(dāng)你對渲染的項(xiàng)沒有固定的 IDs 時(shí),作為最后的手段,你可以使用項(xiàng)的索引作為一個(gè) key:

const todoItems = todos.map((todo, index) =>
  // Only do this if items have no stable IDs
  <li key={index}>
    {todo.text}
  </li>
);

我們不建議使用索引作為鍵,如果列表項(xiàng)重新排序,那將是緩慢的。如果你感興趣的話可以閱讀深入講解為什么鍵是必需的。

提取帶鍵的組件

鍵只有在數(shù)組的上下文環(huán)境中有意義。

例如,你提取一個(gè)ListItem組件,你應(yīng)該在數(shù)組的<ListItem />元素上使用 key,而不是在ListItem本身的根元素<li>上。

例子:錯(cuò)誤的 key 用法

function ListItem(props) {
  const value = props.value;
  return (
    // Wrong! There is no need to specify the key here:
    <li key={value.toString()}>
      {value}
    </li>
  );
}

function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    // Wrong! The key should have been specified here:
    <ListItem value={number} />
  );
  return (
    <ul>
      {listItems}
    </ul>
  );
}

const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
  <NumberList numbers={numbers} />,
  document.getElementById('root')
);

例子:改正后的 key 用法

function ListItem(props) {
  // Correct! There is no need to specify the key here:
  return <li>{props.value}</li>;
}

function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    // Correct! Key should be specified inside the array.
    <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')
);

CodePen上試試。

一個(gè)好的經(jīng)驗(yàn)法則是:map()調(diào)用內(nèi)部的元素需要鍵。

在兄弟姐妹之間的鍵必須是唯一的

數(shù)組內(nèi)使用的鍵在它們的兄弟姐妹之間必須是唯一的。然而它們不需要在全局唯一。當(dāng)我們生成兩個(gè)不同的數(shù)組時(shí)可以使用相同的鍵。

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 World', content: 'Welcome to learning React!'},
  {id: 2, title: 'Installation', content: 'You can install React from npm.'}
];
ReactDOM.render(
  <Blog posts={posts} />,
  document.getElementById('root')
);

CodePen上試試。

鍵的作用是給 React 提示,但它們不會傳遞給你的組件。如果在你的組件中需要相同的值,使用不同的名字明確的作為 prop 傳遞它。

const content = posts.map((post) =>
  <Post
    key={post.id}
    id={post.id}
    title={post.title} />
);

上面的例子中,Post組件可以讀取props.id,但不能讀取props.key

在 JSX 中插入 map()

在上述例子中,我們聲明了一個(gè)獨(dú)立的listItems變量并包含在 JSX 中。

function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    <ListItem key={number.toString()}
              value={number} />
  );
  return (
    <ul>
      {listItems}
    </ul>
  );
}

JSX 允許在大括號中插入任意表達(dá)式,所以我們可以內(nèi)聯(lián)map()的結(jié)果:

function NumberList(props) {
  const numbers = props.numbers;
  return (
    <ul>
      {numbers.map((number) =>
        <ListItem key={number.toString()}
                  value={number} />
      )}
    </ul>
  );
}

CodePen上試試。

有時(shí)這會產(chǎn)生清晰的代碼,但這種風(fēng)格也會被濫用。就像在 JavaScript 中,它由你決定是否值得為了可讀性提取一個(gè)變量。記住,如果map()體有太多的嵌套,這是提取組件的好時(shí)機(jī)。

下一步

表單

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 首先,我們來看下如何在JavaScript中轉(zhuǎn)換列表。下面給出的代碼里,我們使用map()函數(shù)獲取一組數(shù),然后加倍...
    莫銘閱讀 582評論 0 1
  • 最近看了一本關(guān)于學(xué)習(xí)方法論的書,強(qiáng)調(diào)了記筆記和堅(jiān)持的重要性。這幾天也剛好在學(xué)習(xí)React,所以我打算每天堅(jiān)持一篇R...
    gaoer1938閱讀 1,730評論 0 5
  • 本筆記基于React官方文檔,當(dāng)前React版本號為15.4.0。 1. 安裝 1.1 嘗試 開始之前可以先去co...
    Awey閱讀 7,807評論 14 128
  • React版本:15.4.2**翻譯:xiyoki ** 首先,讓我們回顧一下如何在Javascript中轉(zhuǎn)換列表...
    前端xiyoki閱讀 315評論 0 0
  • 這篇筆記主要包含 Vue 2 不同于 Vue 1 或者特有的內(nèi)容,還有我對于 Vue 1.0 印象不深的內(nèi)容。關(guān)于...
    云之外閱讀 5,082評論 0 29