Hi!大家好啊!其實最後五篇的時候一直在作品中間鬼打牆XD,有時候想說這樣做,睡前又想說可以這樣做,起床改一改上班又想到另外一個作法,總之真的覺得第一次使用組件來實作作品有點硬,不過如果沒有實作永遠不會了解怎麼使用對吧!就像二十天前跨出鐵人賽的那一步一樣,所以在最後實作的過程,有可以改進的再麻煩各位大大指教了!謝謝!
好的!首先進入正文吧!今天要把存在store中的資料讀出來,然後列出像下方的樣子:
今天要做的流程大概是用一個組件來讀資料,取到所有的事項資料後再用迴圈將每筆事項用組件讀出來,因為先有裡面的組件,才能夠用迴圈,所以我們先從內部list的部分開始做。
首先建立一個list的組件:
list.jsx
import React from "react"
class List extends React.Component {
}
export { List }
之後分成三個部分說明:
在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)
}
接著來撰寫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;
            }
    }
}
最後是輸出組件的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>
    )
}
然後可不要忘記幫list的div寫下樣式哦!他也有自己的樣子:
index.css
//事項框框的樣式
.list{
    background: #F2F2F2;
    height: 100px;
    width: 620px;
    border-radius: 5px;
    text-align: left;
}
//要離上面20px
.listBlock{
    margin-top: 20px;
}
以為就這樣嗎?nono!還有下面的Icon:
讓我們在list的div最後寫下顯示Icon的程式碼吧!是list的div哦!不是listBlock!下方一樣是透過判斷來看是否要顯示Icon,如果對應的欄位沒有資料就輸出空字串,然後日期的部份因為他是取月/日這樣子的格式,所以我做了一些處理,至於class的icon部分是為了讓他們互相保持一些距離,這樣比較好看:
<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中,最後再將存著所有事項資料的變數Lists在return中輸出。
至於從redux取資料的步驟更單純,首先要先寫下我們要的資料:
const mapStateToProps = state => {
    return { data: state }       
}
我在上方指定用this.props.data做map,所以這裡取資料就要把資料放到data中,如果這邊的data改成其他像是listsData那上方ConnectTodoLists的迴圈就要改成對this.props.listsData。
再來就能夠將上方的ConnectTodoLists和要取的資料ConnectTodoLists做connect,得到的新組件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,運行出來之後的首頁就長這樣!
是不是有點像一回事了!而且當我隨便新增一個事項:
新增完後就同步跑出來了!
那在此附上今天進度的程式碼:
GitHub程式目錄連結
GitPage頁面連結
剩下的話其實有點累了XD,文章結尾我就不多說了,因為開頭說了滿多的,哈哈哈!真心感謝陪我一路走到這裡的大家!講得好像結束一樣,不過最後幾天特別有感慨。
文章中如果有任何問題,再麻煩各位留言告訴我,小弟看到後會盡快回覆或修改補充文章內容!謝謝大家