iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 26
7
Modern Web

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

[筆記][React]來做個作品吧!待辦事項「todolist」篇(6)-上吧!迴圈!

  • 分享至 

  • xImage
  •  

Hi!大家好啊!其實最後五篇的時候一直在作品中間鬼打牆XD,有時候想說這樣做,睡前又想說可以這樣做,起床改一改上班又想到另外一個作法,總之真的覺得第一次使用組件來實作作品有點硬,不過如果沒有實作永遠不會了解怎麼使用對吧!就像二十天前跨出鐵人賽的那一步一樣,所以在最後實作的過程,有可以改進的再麻煩各位大大指教了!謝謝!


好的!首先進入正文吧!今天要把存在store中的資料讀出來,然後列出像下方的樣子:
https://ithelp.ithome.com.tw/upload/images/20181025/20106935qczbDAszdl.png

今天要做的流程大概是用一個組件來讀資料,取到所有的事項資料後再用迴圈將每筆事項用組件讀出來,因為先有裡面的組件,才能夠用迴圈,所以我們先從內部list的部分開始做。

首先建立一個list的組件:
list.jsx

import React from "react"

class List extends React.Component {

}

export { List }

之後分成三個部分說明:

  1. constructor內部來接外面傳進來的事項資料this.props.listData,所以等等記得要傳入listData中這邊才接的到,然後因為在顯示事項的時候,也可以同時標記已完成和是否重要,所以也寫一個changeState事件供他使用,讓組件可以同步更新目前的資料狀態,state只需要紀錄會變化的資料,所以只填寫兩個欄位,其他固定無法修改的就用props處理。

    constructor(props) {
        super(props)
        this.state = {important:this.props.listData.important
                     ,complete:this.props.listData.complete}
        this.changeState = this.changeState.bind(this)
    }
    
  2. 接著來撰寫changeState事件,和之前在inputTasks組件內寫過的差不多,只是減少為兩種情況,因為只有已完成或是否重要而已,這邊要注意我是用參數type來判斷是哪一種資料哦:

    changeState(type) {
        switch (type) {
            case "complete": {
                this.setState({ complete: window.event.target.checked })
                break;
            }
            case "important": {
                if (this.state.important == '')
                    this.setState({ important: 'Y' })
                else
                    this.setState({ important: '' })
                break;
                }
        }
    }
    
  3. 最後是輸出組件的render的部分,這邊和InputTasks很像,因為都是顯示是否完成的勾勾、事項名稱、是否重要的星星三個資料,而且也要依照資料來添加class,而class就沿用之前我們使用過的那些,而下方的changeState要給對應的參數:

    render() {
        return (
            <div class="listBlock">
                <div class={' list ' + 
                        (this.state.important == 'Y' ? ' important ' : '')}>
    
                    <input type="checkbox" class="taskChk" 
                            checked={this.state.complete} 
                            onChange={this.changeState.bind(this,'complete')} />
    
                    <input type="text" 
                            class={' taskTitle ' + 
                                    (this.state.complete ? ' complete ' : '') +
                                    (this.state.important ? ' important ' : '') }
                            value={this.props.listData.name}  />
    
                    <i class={this.state.important == 'Y' ? 
                            ' fas fa-star fa-lg iconImportant icon' : 
                            ' far fa-star fa-lg icon'}
                            onClick={this.changeState.bind(this,'important')}></i>
    
                    <i class="fas fa-pen fa-lg icon"></i>
                </div>
            </div>
        )
    }
    

    然後可不要忘記幫listdiv寫下樣式哦!他也有自己的樣子:
    index.css

    //事項框框的樣式
    .list{
        background: #F2F2F2;
        height: 100px;
        width: 620px;
        border-radius: 5px;
        text-align: left;
    }
    
    //要離上面20px
    .listBlock{
        margin-top: 20px;
    }
    

    以為就這樣嗎?nono!還有下面的Icon
    https://ithelp.ithome.com.tw/upload/images/20181025/20106935jEJzS5ASbB.jpg

    讓我們在listdiv最後寫下顯示Icon的程式碼吧!是listdiv哦!不是listBlock!下方一樣是透過判斷來看是否要顯示Icon,如果對應的欄位沒有資料就輸出空字串,然後日期的部份因為他是取月/日這樣子的格式,所以我做了一些處理,至於classicon部分是為了讓他們互相保持一些距離,這樣比較好看:

    <div class="listIcon">
        {this.props.listData.date != '' ?
            <i class="far fa-calendar-alt icon"></i> : ''}
        {this.props.listData.date != '' ?
            ` ${this.props.listData.date.substring(5).replace('-', '/')} ` : ''}
    
        {this.props.listData.file != '' ?
            <i class="fas fa-file icon"></i> : ''}
    
        {this.props.listData.commit != '' ?
            <i class="far fa-comment-dots icon"></i> : ''}
    </div>
    

    這裡下排Icon的字體沒有那麼大,還有一些位置的調整,而且顏色也是灰色的,這些樣式就另外寫在listIcon中處理:

    .listIcon{
        color: #757575;
        margin-top: -15px;
        margin-left: 25px;
        font-size: 16px;
    }
    

List的部分結束之後!要來把資料從store讀出來,然後下迴圈帶入組件中,別忘了為迴圈內的每一項資料帶入key哦!我們先新增個TodoLists來處理這件事情,組件名稱我前面有加Connect代表他待會會被用來connect來產生綁定的組件:
TodoLists.jsx

import React from "react"
import {connect} from "react-redux"
import {List} from "../List"

class ConnectTodoLists extends React.Component{
    render(){
        let Lists = this.props.data.map((item)=>{
            return <List key={item.id} listData = {item} />
        })

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

上方的組件很單純,就只是對所有的資料做迴圈,然後把每筆事項資料都個別丟到List組件中,List輸出後再丟進變數Lists中,最後再將存著所有事項資料的變數Listsreturn中輸出。

至於從redux取資料的步驟更單純,首先要先寫下我們要的資料:

const mapStateToProps = state => {
    return { data: state }       
}

我在上方指定用this.props.datamap,所以這裡取資料就要把資料放到data中,如果這邊的data改成其他像是listsData那上方ConnectTodoLists的迴圈就要改成對this.props.listsData

再來就能夠將上方的ConnectTodoLists和要取的資料ConnectTodoListsconnect,得到的新組件TodoLists就能拿來匯出。

const TodoLists = connect(mapStateToProps)(ConnectTodoLists)

export {TodoLists}

嘿嘿!匯出後還有一個步驟啊!別忘記了,最後將MyTasks.jsx打開加入剛剛做的TodoLists組件,接著把它放在之前做的AddTask組件下面:

import React from "react"
import {AddTask} from "../AddTask"
import {TodoLists} from "../TodoLists"

class MyTasks extends React.Component{
    render(){
        return (
            <div class="InputTasksForm">
                <AddTask />
                <TodoLists />
            </div>
        )
    }
}

export { MyTasks }

搞定後,從椅子上站起來,伸個懶腰,點下webpack-dev-server,運行出來之後的首頁就長這樣!
https://ithelp.ithome.com.tw/upload/images/20181025/20106935bGcpt2dteZ.png

是不是有點像一回事了!而且當我隨便新增一個事項:
https://ithelp.ithome.com.tw/upload/images/20181025/20106935aT8enPXz81.png

新增完後就同步跑出來了!
https://ithelp.ithome.com.tw/upload/images/20181025/20106935j0EDtDnxHB.png

那在此附上今天進度的程式碼:
GitHub程式目錄連結
GitPage頁面連結


剩下的話其實有點累了XD,文章結尾我就不多說了,因為開頭說了滿多的,哈哈哈!真心感謝陪我一路走到這裡的大家!講得好像結束一樣,不過最後幾天特別有感慨。

文章中如果有任何問題,再麻煩各位留言告訴我,小弟看到後會盡快回覆或修改補充文章內容!謝謝大家/images/emoticon/emoticon41.gif


上一篇
[筆記][React]來做個作品吧!待辦事項「todolist」篇(5)-寫下新增資料的里程碑
下一篇
[筆記][React]來做個作品吧!待辦事項「todolist」篇(7)-讓組件重用起來
系列文
一步一腳印的React旅程30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

2
SunAllen
iT邦研究生 1 級 ‧ 2018-10-31 19:51:30

加油! 再幾天就達陣了! /images/emoticon/emoticon12.gif

神Q超人 iT邦研究生 5 級 ‧ 2018-10-31 20:06:17 檢舉

我這個月來每天都在想著那一天/images/emoticon/emoticon37.gif

SunAllen iT邦研究生 1 級 ‧ 2018-10-31 20:07:33 檢舉

/images/emoticon/emoticon37.gif

我要留言

立即登入留言