iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 8
7
Modern Web

一步一腳印的React旅程系列 第 8

[筆記][React]用 for 迴圈處理Component

HI!大家好,這一篇和前一篇應該會比較輕鬆,畢竟說的都是天天陪伴著大家的語法XD,加上在JSX中處理Element真的變得很容易上手,因為就和原生的JavaScript一樣嘛!沒有地方好苦腦的,哈哈!所以這兩天就當作過了第一個禮拜的門檻,輕鬆一點吧!


for迴圈

那,都第八篇了,應該也不用說什麼客套話了XD,就直接進入範例吧!在不使用迴圈的一般情況下,我們可以這樣處理組件列表:

class TodoList extends React.Component{
    constructor(props){
        super(props)
    }
    
    render(){
        let lists = [<li>打文章</li>,<li>寫程式</li>,<li>耍廢</li>]
        return (
            <ul>
                //JSX中的JS變數要用花括號包著
                {lists}
            </ul>
        )
    }
}

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

上方將所有的list事項都放lists陣列中,最後把整個lists放進<ul>中,結果會如下:
https://ithelp.ithome.com.tw/upload/images/20180925/20106935SqNLUtQIwl.png

所以從上面的例子,就可以知道說,只要放進陣列就可以了!沒錯!就是這樣就可以了,所以當我們透過ajax從後端取得列表資料時,就可以將render()寫成這樣:

    render(){
        //假設有個待辦事項的陣列
        let arrLists = ['打文章','寫程式','耍廢']
        
        //先建立一個空陣列
        let lists = [];
        
        //用迴圈將代辦事項的內容一個個放進空陣列中
        for(let i=0;i<=arrLists.length-1;i++){
            //記得在JSX中使用JS變數要用花括號包著
            lists.push(<li>{arrLists[i]}</li>)
        }

        return (
            <ul>
                {lists}
            </ul>
        )
    }

雖然上面的寫法已經詮釋完迴圈的基本用法,但是在JavaScript中的陣列還有個map()函式,他可以去巡訪陣列中每個位置的值,並將他們傳入function做處理後傳出,以下快速學習(詳情可以看這裡):

//宣告一個陣列A
let arrA = [1,2,3,4,5]

//宣告另一個陣列B,並對A使用map()讓每個數字都*2放進B中
let arrB = arrA.map(function(num){ return num*2 })

//把陣列B印出來
console.log(arrB) //[2, 4, 6, 8, 10]

好的!學習完後,我們試著用map改寫render吧:

    render(){
        let arrLists = ['打文章','寫程式','耍廢']
        
        //在巡訪時將arrLists用<li>包起來回傳
        let lists = arrLists.map(function(list){return <li>{list}</li>})

        return (
            <ul>
                {lists}
            </ul>
        )
    }

當然如果想要再潮一點用盡ES6語法,也可以把mapfunction改成箭頭函式:

    render(){
        let arrLists = ['打文章','寫程式','耍廢']

        let lists = arrLists.map((list) => <li>{list}</li>)

        return (
            <ul>
                {lists}
            </ul>
        )
    }

以上三種方法都會呈現出和第一張圖一樣的結果,至於大家喜歡哪一種方法,就任君挑選囉!
GitHub程式碼連結
GitPage頁面連結

key值

這裡要提到的key和現在浮現在大家腦裡的key可能不太一樣,這裡的key是為了要讓react好渲染畫面用的。

以待辦事項來說,在我們有一個以上的項目的時候,如果列表的第一行增加了一個待辦事項,那原本待辦事項的位置都會向下移,造成重新渲染畫面,資料少的話還好,但資料一多那效能可能會有感的下降。

為了避免這個情況react,會再重新渲染畫面之前,去比對key值,如果相同,那就會略過,不會重新覆蓋DOM,就像在[筆記][React]關於Components的那件小事這篇文章中提的時間例子一樣,經過比對就只會重新渲染不同的地方而已。

那麼!key值該怎麼設定呢?這個比大家想像中的還要簡單:

class TodoList extends React.Component{
    constructor(props){
        super(props)
    }
    
    render(){
        //這裡一樣用map把陣列中每個元素都找出來
        let lists = this.props.objLists.map((list) => 
        /*key值的資料就給唯一值id指定*/
        <li key={list.id}>{list.list}</li>)

        return (
            <ul>
                {lists}
            </ul>
        )
    }
}

//假設我們拿到的陣列中,有每一個資料的物件
let objLists = 
[{id:'a',list:'打文章'},{id:'b',list:'寫程式'},{id:'c',list:'耍廢'}]

//將該陣列用props的方式傳入class中處理
ReactDOM.render(<TodoList objLists={objLists} />,document.getElementById('root'))

雖然看起來很簡單,但是還是有需要注意的地方:

  1. 必須是唯一值,像全天下所有key的意思一樣,必須是唯一react才能夠比對,如果再是在開發版,有重複的話雖然畫面可以正常渲染,但console內會出現錯誤提示:
    https://ithelp.ithome.com.tw/upload/images/20180925/20106935BZigM4rZfI.png
    ps.沒設定key值其實也會有提示:
    https://ithelp.ithome.com.tw/upload/images/20180925/20106935u3YhvFADGs.png
  2. 這個key值並不會被當屬性渲染出來,所以如果要另外操作的話,就得再設定另一個屬性,例如:
    render(){
        let lists = this.props.objLists.map((list) => 
        /*把唯一值也設定到id身上*/
        <li key={list.id} id={list.id}>{list.list}</li>)
    
        return (
            <ul>
                {lists}
            </ul>
        )
    }
    
    渲染出來的畫面只會有id不會有key
    https://ithelp.ithome.com.tw/upload/images/20180926/20106935C7qScSULFL.png
  3. 如果沒有使用key的話,用陣列的索引會是最後最後的下下策:
    render(){
        //為map增加第二個index的引數,他會記錄目前是第幾個索引
        let lists = this.props.objLists.map((list,index) => 
        /*將索引設定為key值*/
        <li key={index}>{list.list}</li>)
    
        return (
            <ul>
                {lists}
            </ul>
        )
    }
    
    但是第三點這個方式不如不要用,因為他每次都會以索引為key值去判斷,所以當我們在陣列第一個位置增加一筆資料,那原本的項目都會向下移動,索引也會發生變化,等於原本的1223,然後值就全部寫到對應的新key中,這麼一來就和重新渲染沒什麼兩樣,key和值也會不斷變動,所以為了效能還是乖乖自行加上唯一值吧!因為以索引當key就和沒設一樣,只是不會出現錯誤而已。

GitHub程式碼連結
其實長得一樣的GitPage頁面連結


以上是在react使用迴圈的方法和注意事項,如果有任何問題的話,再麻煩各位大大留言告訴我,我會再把他補充上去的,最後感謝各位大大的觀看/images/emoticon/emoticon41.gif

參考文章:

  1. https://reactjs.org/docs/lists-and-keys.html
  2. https://note.pcwu.net/2017/03/23/react-array-key/
  3. https://medium.com/@robinpokorny/index-as-a-key-is-an-anti-pattern-e0349aece318

上一篇
[筆記][React]用 if 條件式來控制Component
下一篇
[筆記][React]受不受控的Component與Form表單
系列文
一步一腳印的React旅程30

尚未有邦友留言

立即登入留言