使用react實(shí)現(xiàn)一個(gè)todolist

效果如下:


image.png

分析組件:
1.頭部:標(biāo)題
2.內(nèi)容:列表項(xiàng)+刪除
3.尾部:添加列表項(xiàng)
4.包裹所有組件的App.js,在這個(gè)大的組件包含所有的屬性及操作


image.png

標(biāo)題

//header.js
import React,{Component } from 'react';
import "./header.css"

class Header extends Component{
    render(){
        return (
            <div className="header">
                任務(wù)便簽
            </div>
        )
    }
}
export default Header

在App.js引出:

<Header />

尾部添加

分析:
1.因?yàn)樗械牟僮鞫紩?huì)在App.js里面去操作,所以子組件的所以初始化的屬性都需要通過(guò)父組件傳值給子組件;比如輸入框的value屬性值
2.通過(guò)onChange事件獲取用戶輸入的值,試想:怎么讓用戶輸入的值顯示在輸入框里面呢:也就是說(shuō)我怎么把輸入的值賦值給父組件的value,這就需要使用子組件觸發(fā)父組件的函數(shù),并傳值給父組件:this.props.這個(gè)方法(傳的值)
3.當(dāng)點(diǎn)擊添加按鈕的時(shí)候,我需要將輸入的值追加到定義的List,同樣在子組件點(diǎn)擊按鈕,觸發(fā)父組件的方法
footer.js

class Header extends Component{
        handleInput(e){
          this.props.handleInput(e.target.value)
        }
        handleAdd(){
          this.props.handleAdd()
        }
     render(){
        return (
            <div className="footer">
                <input type="text" value={this.props.value} onChange={this.handleInput.bind(this)}>
                              <button onChlick={this.handleAdd.bind(this)}>添加</button>
            </div>
        )
    }
}
//父組件
constructor(props) {
        super(props)
        this.state = {
            list: [{
                name: 'learn english',
                status: 0
            }, {
                name: 'Learn guitar',
                status: 0
            }, {
                name: 'weight less than 100',
                status: 0
            }, {
                name: 'have 100,000 deposit',
                status: 0
            }],
            value:"",
        }
    }
//父組件接受子組件傳的值
handleInput(val){
  this.setData({
    value:val
  })
}
handleAdd(){
  if(!this.state.value){
    return false
  }
  this.setState({
    list:[...this.state.list,{
      name:this.state.value,
      status:0,
    }],
  value:""
  })
}
render{
  return (
  <Footer value={this.state.list} handleInput={this.handleInput.bind(this)} handleAdd={this.handleAdd.bind(this)}  />
)
}

中間列表項(xiàng)

分析:
1.列表項(xiàng)是由一個(gè)單選框,名字,刪除按鈕
2.因?yàn)榱斜眄?xiàng)可能會(huì)有很多,則使用map方法
3.單選框的選中狀態(tài)是由List的status為1才表示已選中,當(dāng)選中狀態(tài)發(fā)生改變時(shí),怎么讓list的status實(shí)時(shí)去改變呢,所以需要出發(fā)父組件的方法,
4.當(dāng)該列表項(xiàng)為選中時(shí),則該文字會(huì)加上刪除線:利用text-decoration-line:值為"line-through"時(shí)表示文字中間部分畫(huà)線
5.點(diǎn)擊刪除按鈕是需要?jiǎng)h除當(dāng)前用戶點(diǎn)擊的那一行,所以怎么判斷用戶是當(dāng)前那一行是一個(gè)問(wèn)題:
6.已完成的數(shù)量是表示status為1的個(gè)數(shù)

// this.handleclick.bind(this,要傳的參數(shù))  handleclick(傳過(guò)來(lái)的參數(shù),event)
class ListItem extends Component{
    handleFished(name){
        // 子組件向父組件傳值
        // 在子組件點(diǎn)擊的li得到的值,交給父組件去做交互
        this.props.handleFished(name);
    }
    handleDelete(name){
        this.props.handleDelete(name)
    }
    render(){
        return (
            <ul>
                {this.props.data.map((item,index)=>{
                    return (
                        <li key={index} className="listItem">
                            <input type="checkbox" checked={item.status===1} onChange={this.handleFished.bind(this,item.name)} />
                            <span style={{textDecorationLine:item.status===0?'none':'line-through'}}>{item.name}</span>
                            <button className="delete" onClick={this.handleDelete.bind(this,item.name)}>刪除</button>
                        </li>
                    )
                })}
                <li>已完成:{this.props.finished}/總數(shù):{this.props.data.length}</li>
            </ul>
        )
    }
}
export default ListItem

父組件:

constructor(props) {
        super(props)
        this.state = {
            list: [{
                name: 'learn english',
                status: 0
            }, {
                name: 'Learn guitar',
                status: 0
            }, {
                name: 'weight less than 100',
                status: 0
            }, {
                name: 'have 100,000 deposit',
                status: 0
            }],
            finished:0,//已完成的個(gè)數(shù)
        }
}
handleFished(name){
  const list=[];
  let sum=0;
  this.state.list.forEach((item,index){
    //判斷用戶點(diǎn)擊的是當(dāng)前所點(diǎn)擊的那一行
    if(item.name=name){
      let val=this.state.list[index]
      let obj={
        name:val.name,
        status:val.status===0?1:0
      }
      list.push(Object.assign({},obj))
      this.setState({
        list:list
      },()=>{
        this.state.list.forEach(item=>{
          if(item.status===1){
            sum++;
          }
          this.setState({
            finished:sum
          })
        })
      })
    } else{
      list.push(item)
    }
  })

}
handleDelete(name){
  let arr=this.state.list.filter((item)=>{
            return item.name!==name
        })
        this.setState({
            list:arr
        })
}
render(){
  return(
    <ListItem data={this.state.list} finished={this.state.finished} handleFished={this.handleFished.bind(this)} handleDelete={this.handleDelete.bind(this)}  />
  )
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容