React经典案例todoList记录

React经典案例todoList记录

虽然是简单的案例,但值得学习,简单记录了下todoList的案例、代码结构如下,忽略css部分
在这里插入图片描述
**

话不多说,上代码
1、App.jsx代码:

import React, { Component } from 'react'
import Header from './compoents/Header/index'
import List from './compoents/List'
import Footer from './compoents/Footer'
import './App.css'
export default class App extends Component {

  //状态在哪里,操作状态的方法就写在哪里

  //初始化状态
  state = {
    todos:[
      {id:'001',name:'吃饭',done:true},
      {id:'002',name:'睡觉',done:true},
      {id:'003',name:'写代码',done:false},
      {id:'004',name:'逛街街',done:false},
    ]
  }

  //函数
  //addTodo用于添加一个todo,接收的参数是todo对象
  addTodo = (todoObj)=>{
    console.log("App",todoObj)
    //获取原todos
    const {todos} = this.state
    //在原来的todos上追加一个todo
    const newTodos = [todoObj,...todos]
    //更新状态
    this.setState({todos:newTodos})
  }

  //更新item是否完成 用于更新一个todo对象
  updateTodo=(id,done)=>{
    //函数体
    //获取状态中的todos
    const {todos} = this.state
    //判断勾选的item是哪一项去进行更新
    //加工数据
     const newTodos = todos.map((todoObj)=>{
      //测试
      // let obj = {a:1,b:2}
      // let obj2 = {...obj,b:3}
      // console.log(obj2)//打印结果:{a:1,b:3}
      if(todoObj.id===id){
        //返回新的对象
        return {...todoObj,done:done}
      }else{
        //无匹配上 直接返回
        return todoObj
      }
    })
    this.setState({todos:newTodos})
  }

  //删除todo的回调函数
  deleteTodo = (id)=>{
    //函数体
    //获取原来的todos
    const {todos} = this.state
    //删除指定id的todo对象
    //从数组里面删除指定id的元素
    const newTodos = todos.filter((todoObj)=>{
      return todoObj.id !==id
    })
    //更新状态
    this.setState({todos:newTodos})

  }

  //全选
  checkAllTodo=(done)=>{
    //获取原来的todos
    const {todos} = this.state
    //加工数据
    const newTodos = todos.map((todoObj)=>{
      return {...todoObj,done:done}
    })
    //更新状态
    this.setState({todos:newTodos})

  }
  //清除所有已完成
  clearAllDone = ()=>{
    //获取原来的todos
    const {todos} = this.state
    //加工数据
    const newTodos = todos.filter((todoObj)=>{
      return todoObj.done ===false
    })
    //更新状态
    this.setState({todos:newTodos})
  }

  render() {
    const {todos} = this.state
    return (
      <div className='todo-container'>
        <div className='todo-wrap'>
        <Header addTodo={this.addTodo}/>
        <List todos = {todos} updateTodo={this.updateTodo} deleteTodo={this.deleteTodo}/>
        <Footer todos = {todos} checkAllTodo={this.checkAllTodo} clearAllDone={this.clearAllDone}/>
      </div>
      </div>
    )
  }
}

2、Header.jsx代码:

import React, { Component } from 'react'
import PropTypes from 'prop-types'
import {nanoid} from 'nanoid'
import './index.css'

console.log(nanoid())
export default class Header extends Component {

  //对接收的props进行:类型、必要性的限制
  static propTypes = {
    addTodo:PropTypes.func.isRequired
  }

  //键盘回车事件
  handleKeyUp = (event)=>{
    //函数体
    //event.keyCode原生获取键盘键下对应key值
    // const {keyCode,target} = event
    // if(keyCode!==13) return
    // console.log(target.value)

    //keyCode已废除使用 直接使用key
    //解构赋值key,target
    const {key,target} = event
    //判断是否是回车案件
    if(key!=='Enter') return
    console.log(target.value,key);
    //子组件给父组件传值,要求父给子通过props传的是一个函数
    //子通过调用父的函数达到给父传值的目的
    //准备好一个todo对象
    //判断:添加的name不能为空
    if(target.value.trim()===''){
      alert("输入不能为空")
      return
    }
    const todoObj = {id:nanoid(),name:target.value,done:false}
    //将todoObj传递给父组件
    this.props.addTodo(todoObj)
    //nanoid()生成唯一字符串保证标志唯一
    //清空输入
    target.value = ""
  }
  render() {
    return (
      <div className='to-header'>
        <input onKeyUp={this.handleKeyUp} type="text" placeholder='请输入你的任务名称,按回车键确认'/>
      </div>
    )
  }
}

3、List.jsx代码:

import React, { Component } from 'react'
import PropTypes from 'prop-types'
import Item from '../Item'
import './index.css'

export default class List extends Component {
    //对接收的props进行:类型、必要性的限制
    static propTypes = {
      todos:PropTypes.array.isRequired,
      updateTodo:PropTypes.func.isRequired,
      deleteTodo:PropTypes.func.isRequired,
    }
  render() {
    const {todos,updateTodo,deleteTodo} = this.props
    console.log('列表数据',todos)
    return (
      <ul className='todo-main'>
        {
          todos.map((todo,index)=>{
            //拆分传递
            // return <Item key={todo.id} id={todo.id} name={todo.name} done={todo.done}/>
            //批量传递...
            return <Item key={todo.id} {...todo} updateTodo={updateTodo} deleteTodo={deleteTodo}/>
          })
        }
      </ul>
    )
  }
}

4、Item.jsx代码:

import React, { Component } from 'react'
import './index.css'

export default class Item extends Component {

  //维护一个状态值,用于标识鼠标是否移入状态
  state = {mouse:false}

  //鼠标移入移出回调
  handMouse=(flag)=>{
    return ()=>{
      //根据鼠标移入移出与否更新state状态
      this.setState({mouse:flag})
      //console.log(this.state.mouse)
    }
  }
  //复选框是否勾选事件接收参数id
  handCheck=(id)=>{
    //函数体
    return(event)=>{
      //event.target.checked获取复选框是否勾选状态
      console.log(id,event.target.checked)
      this.props.updateTodo(id,event.target.checked)
    }
  }
  //删除todo的回调
  handDelete=(id)=>{
    //函数体
    console.log("删除的todo的id",id)
    if(window.confirm("确认删除吗?")){
      this.props.deleteTodo(id)
    }
  }
  render() {
    const {id,name,done} = this.props
    const {mouse} = this.state
    return (
      <li style={{backgroundColor:mouse?'#ddd':'white'}} onMouseEnter={this.handMouse(true)} onMouseLeave={this.handMouse(false)}>
          <label>
            <input type="checkbox" checked={done} onChange={this.handCheck(id)}/>
            <span>{name}</span>
          </label>
          <button onClick={()=>{this.handDelete(id)}} className='btn btn-danger' style={{display:mouse?'block':'none'}}>删除</button>
        </li>
    )
  }
}

5、Footer.jsx代码:

import React, { Component } from 'react'
import './index.css'

export default class Footer extends Component {

  //全选框change函数
  handleCheckAll=(event)=>{
    //函数体
    this.props.checkAllTodo(event.target.checked)
  }
  //清除已完成的回调函数
  handleClearAllDone = ()=>{
    this.props.clearAllDone()
  }

  render() {
    const {todos} = this.props
    //计算已完成的个数使用数组的reduce方法
    const doneCount = todos.reduce((pre,todo)=>{return pre+(todo.done?1:0)},0)
    console.log(doneCount,'已完成')
    //总数
    const total = todos.length
    return (
      <div className='todo-footer'>
        <label><input type="checkbox" onChange={this.handleCheckAll} checked={doneCount===total&&total!==0?true:false}/>
        </label><span>已完成{doneCount}</span>/全部{total}
        <button onClick={this.handleClearAllDone} className='btn btn-danger'>清除已完成任务</button>
      </div>
    )
  }
}

效果如下:新增、单个删除、删除已完成、完成勾选、取消勾选、全选、全部取消勾选、计数**
兄弟萌赶快试试吧
在这里插入图片描述代码如下:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值