嗨嗨!大家好啊!今天來輕鬆一點點(其實每天都不太難啦XD),昨天已經能將資料用迴圈寫進組件輸出到畫面上了!接下來我們來展開資料的編輯畫面!這篇會採組件重用的邏輯來做到這件事情,那進入正文吧!
首先看一下資料編輯的畫面:
是不是覺得有點熟悉?沒錯!他就跟新增時的畫面一模一樣!所以我們也不需要再重新做一個組件了,直接使用之前做的InputTask就好,那要改的時候先打開昨天製作的List.jsx檔案,我們需要在裡面加上的東西有幾點:
List上設定點擊事件,點擊後可以將InputTask渲染出來。List接收到的待辦事項資料經由props傳到InputTask中。為了第三點的到來,就趕緊開工吧XD,一起打開List.jsx:
state中多新增一個屬性,幫我們保管要輸出的InputTask組件內容:
constructor(props) {
    super(props)
    this.changeState = this.changeState.bind(this)
    this.list = React.createRef()
    this.state = {important:this.props.listData.important
                 ,complete:this.props.listData.complete
                 ,editTasks:null}
}
render的時候就能夠固定輸出他,什麼意思呢?看下去吧!render中輸出剛剛的this.state.editTasks內的值,因為他平常是null,所以一直待著也不會有什麼影響:
render() {
    //初始化組件
    return (
        <div class="listBlock">
            <div class={' list ' + 
                (this.state.important == 'Y' ? ' important ' : '')}>
                {/*因為怕太長所以中間省略*/}
            </div>
            {/*在這裡固定輸出this.state.editTasks*/}
            <div>
                {this.state.editTasks}
            </div>
        </div>
    )
}
InputTask組件寫到this.state.editTasks中,所以新增以下事件設定this.state.editTasks的值,並同時把待辦事項的資料給InputTask:
openEdit() {
    this.setState({editTasks:(<InputTask listData={this.props.listData} />)})
}
props傳給InputTask的closeAdd中,記得我們很久很久之前有寫過這個吧XD
closeEdit() {
    this.setState({editTasks:null})
}
InputTask中,所以把上方的openEdit改成下面這樣:
openEdit(event) {
    this.setState({editTasks:(<InputTask closeAdd={this.closeEdit}
                                        listData={this.props.listData} />)})
}
openEdit設定給List組件的點擊事件:
render() {
    //初始化組件
    return (
        <div class="listBlock">
            <div class={' list ' + 
                (this.state.important == 'Y' ? ' important ' : '')}
                onClick={this.openEdit}>
                {/*因為怕太長所以中間省略*/}
            </div>
        </div>
    )
}
InputTask.jsx做一些小調整,其實沒有太複雜,就只是因為當初在這裡預設state的值全都是空的,但現在不同了,有可能我會接收到從外面傳進來的值,所以在這種情況下我們得在設定state時做一些小調整:
constructor(props) {
    super(props)
    //如果有值的話就寫入值,沒值就預設都空的
    if (this.props.listData) {
        this.state = this.props.listData
    }
    else {
        this.state = { id: '', name: '', date: '', time: '', file: ''
                    , commit: '', important: '', complete: false }
    }
 }
就是上方簡簡單單的調整,那執行來看看吧!
登愣!野生的Bug出現了!當我點下List的任何一處後,雖然編輯畫面跳出來了,但是List本身卻沒有消失:
而且當我只是單純要將它變成已完成或標記重要時,他依然會開啟編輯畫面,總之這兩個問題我們一個一個解決!
List可以在點擊後隱藏,就必須要可以先抓到那個div,但是在組件可以重複使用的狀況下,通常不會為組件內的DOM設定id,否則當組件重用時,就只會有第一個設定id的生效而已,那該怎麼辦呢?就用ref吧!
List的constructor內createRef()
this.list = React.createRef()
ref給點擊後需隱藏的div:
render() {
  //初始化組件
  return (
      <div class="listBlock">
          <div class={' list ' + 
                (this.state.important == 'Y' ? ' important ' : '')}
                onClick={this.openEdit}
                ref={this.list}>
                {/*中間省略*/}
            </div>
            {/*下面雖然不長但也省略*/}
        </div>
    )
}
openEdit和closeEdit兩個事件,當點擊打開時就為他的CSS增加display=none做隱藏,關閉時再把display的none拿掉讓他顯示:
openEdit() {
    this.list.current.style.display = 'none'
    this.setState({editTasks:(<InputTask closeAdd={this.closeEdit}
                                    listData={this.props.listData} />)})
}
closeEdit() {
    this.list.current.style.display = ''
    this.setState({editTasks:null})
}
openEdit,這個其實很簡單,只需要去判斷觸發openEdit事件的元件是什麼就好,那問題來了,該怎麼知道呢?就決定是你了!event!從event判斷如果class不含fa-star和taskChk才顯示編輯畫面:
openEdit(event) {
    if (event.target.className.indexOf('fa-star') === -1 &&
        event.target.className.indexOf('taskChk') === -1) {
        this.list.current.style.display = 'none'
        this.setState({editTasks:(<InputTask closeAdd={this.closeEdit}
            listData={this.props.listData} />)})
    }
}
處理完上面兩個Bug後就能重新執行網頁了!這時候大家的頁面應該不只可以新增,還能夠透過點擊待辦事項的列表顯示詳細資料!只是目前+ SAVE這個按鈕的事件還是新增,明天我們再來將修改資料的事件寫好!讓他能夠再InputTask中修改待辦事項的資料!那以下附上今天進度的GitHub連結:
GitHub程式目錄連結
GitPage頁面連結
到這裡其實會發現,在實作的時候都一一用上前20篇學的所有精華(算精華嗎XD),最後這個作品就算是一個總複習,讓大家也讓我更熟悉組件的開發模式!那最後還是感謝各位大大的觀看,如果文章中有任何問題或是錯誤的地方,還麻煩留言告所我,小弟都會盡快查看並修改或補充文章內容的!謝謝大家