渲染列表數據

列表數據在前端很是常見,咱們常常要處理這種類型的數據,例如文章列表、評論列表、用戶列表…一個前端工程師幾乎天天都須要跟列表數據打交道。html

React.js 固然也容許咱們處理列表數據,但在使用 React.js 處理列表數據的時候,須要掌握一些規則。咱們這一節會專門討論這方面的知識。前端

渲染存放 JSX 元素的數組

假設如今咱們有這麼一個用戶列表數據,存放在一個數組當中:數組

const users = [
  { username: 'Jerry', age: 21, gender: 'male' },
  { username: 'Tomy', age: 22, gender: 'male' },
  { username: 'Lily', age: 19, gender: 'female' },
  { username: 'Lucy', age: 20, gender: 'female' }
]

若是如今要把這個數組裏面的數據渲染頁面上要怎麼作?開始以前要補充一個知識。以前說過 JSX 的表達式插入 {} 裏面能夠聽任何數據,若是咱們往 {} 裏面放一個存放 JSX 元素的數組會怎麼樣?瀏覽器

...

class Index extends Component {
  render () {
    return (
      <div>
        {[
          <span>React.js </span>,
          <span>is </span>,
          <span>good</span>
        ]}
      </div>
    )
  }
}

ReactDOM.render(
  <Index />,
  document.getElementById('root')
)

咱們往 JSX 裏面塞了一個數組,這個數組裏面放了一些 JSX 元素(其實就是 JavaScript 對象)。到瀏覽器中,你在頁面上會看到:前端工程師

審查一下元素,看看會發現什麼:函數

React.js 把插入表達式數組裏面的每個 JSX 元素一個個羅列下來,渲染到頁面上。因此這裏有個關鍵點:若是你往 {} 放一個數組,React.js 會幫你把數組裏面一個個元素羅列而且渲染出來。優化

使用 map 渲染列表數據

知道這一點之後你就能夠知道怎麼用循環把元素渲染到頁面上:循環上面用戶數組裏面的每個用戶,爲每一個用戶數據構建一個 JSX,而後把 JSX 放到一個新的數組裏面,再把新的數組插入 render 方法的 JSX 裏面。看看代碼怎麼寫:this

const users = [
  { username: 'Jerry', age: 21, gender: 'male' },
  { username: 'Tomy', age: 22, gender: 'male' },
  { username: 'Lily', age: 19, gender: 'female' },
  { username: 'Lucy', age: 20, gender: 'female' }
]

class Index extends Component {
  render () {
    const usersElements = [] // 保存每一個用戶渲染之後 JSX 的數組
    for (let user of users) {
      usersElements.push( // 循環每一個用戶,構建 JSX,push 到數組中
        <div>
          <div>姓名:{user.username}</div>
          <div>年齡:{user.age}</div>
          <div>性別:{user.gender}</div>
          <hr />
        </div>
      )
    }

    return (
      <div>{usersElements}</div>
    )
  }
}

ReactDOM.render(
  <Index />,
  document.getElementById('root')
)

這裏用了一個新的數組 usersElements,而後循環 users 數組,爲每一個 user 構建一個 JSX 結構,而後 push 到 usersElements 中。而後直接用表達式插入,把這個 userElements 插到 return 的 JSX 當中。由於 React.js 會自動化幫咱們把數組當中的 JSX 羅列渲染出來,因此能夠看到頁面上顯示:spa

但咱們通常不會手動寫循環來構建列表的 JSX 結構,能夠直接用 ES6 自帶的 map(不瞭解 map 函數的同窗能夠先了解相關的知識再來回顧這裏),代碼能夠簡化成:code

class Index extends Component {
  render () {
    return (
      <div>
        {users.map((user) => {
          return (
            <div>
              <div>姓名:{user.username}</div>
              <div>年齡:{user.age}</div>
              <div>性別:{user.gender}</div>
              <hr />
            </div>
          )
        })}
      </div>
    )
  }
}

這樣的模式在 JavaScript 中很是常見,通常來講,在 React.js 處理列表就是用 map 來處理、渲染的。如今進一步把渲染單獨一個用戶的結構抽離出來做爲一個組件,繼續優化代碼:

const users = [
  { username: 'Jerry', age: 21, gender: 'male' },
  { username: 'Tomy', age: 22, gender: 'male' },
  { username: 'Lily', age: 19, gender: 'female' },
  { username: 'Lucy', age: 20, gender: 'female' }
]

class User extends Component {
  render () {
    const { user } = this.props
    return (
      <div>
        <div>姓名:{user.username}</div>
        <div>年齡:{user.age}</div>
        <div>性別:{user.gender}</div>
        <hr />
      </div>
    )
  }
}

class Index extends Component {
  render () {
    return (
      <div>
        {users.map((user) => <User user={user} />)}
      </div>
    )
  }
}

ReactDOM.render(
  <Index />,
  document.getElementById('root')
)

這裏把負責展現用戶數據的 JSX 結構抽離成一個組件 User ,而且經過 props 把 user 數據做爲組件的配置參數傳進去;這樣改寫 Index 就很是清晰了,看一眼就知道負責渲染 users 列表,而用的組件是 User

key! key! key!

如今代碼運做正常,好像沒什麼問題。打開控制檯看看:

React.js 報錯了。若是須要詳細解釋這裏報錯的緣由,估計要單獨寫半本書。但能夠簡單解釋一下。

React.js 的是很是高效的,它高效依賴於所謂的 Virtual-DOM 策略。簡單來講,能複用的話 React.js 就會盡可能複用,沒有必要的話絕對不碰 DOM。對於列表元素來講也是這樣,可是處理列表元素的複用性會有一個問題:元素可能會在一個列表中改變位置。例如:

<div>a</div>
<div>b</div>
<div>c</div>

假設頁面上有這麼3個列表元素,如今改變一下位置:

<div>a</div>
<div>c</div>
<div>b</div>

c 和 b 的位置互換了。但其實 React.js 只須要交換一下 DOM 位置就好了,可是它並不知道其實咱們只是改變了元素的位置,因此它會從新渲染後面兩個元素(再執行 Virtual-DOM 策略),這樣會大大增長 DOM 操做。但若是給每一個元素加上惟一的標識,React.js 就能夠知道這兩個元素只是交換了位置:

<div key='a'>a</div>
<div key='b'>b</div>
<div key='c'>c</div>

這樣 React.js 就簡單的經過 key 來判斷出來,這兩個列表元素只是交換了位置,能夠儘可能複用元素內部的結構。

這裏沒聽懂沒有關係,後面有機會會繼續講解這部份內容。如今只須要記住一個簡單的規則:對於用表達式套數組羅列到頁面上的元素,都要爲每一個元素加上 key 屬性,這個 key 必須是每一個元素惟一的標識。通常來講,key 的值能夠直接後臺數據返回的 id,由於後臺的 id 都是惟一的。

在上面的例子當中,每一個 user 沒有 id 能夠用,能夠直接用循環計數器 i 做爲 key

...
class Index extends Component {
  render () {
    return (
      <div>
        {users.map((user, i) => <User key={i} user={user} />)}
      </div>
    )
  }
}
...

再看看,控制檯已經沒有錯誤信息了。但這是很差的作法,這只是掩耳盜鈴(具體緣由你們能夠本身思考一下)。記住一點:在實際項目當中,若是你的數據順序可能發生變化,標準作法是最好是後臺數據返回的 id 做爲列表元素的 key

相關文章
相關標籤/搜索