07_todoList小练习

TodoList小练习

todoList案例相关知识点

  • 拆分组件、实现静态组件,注意: className、 style的写润Ⅰ

  • 动态初始化列表,如何确定将数据放在哪个组件的state中?

    • 某个组件使用:放在自身的state中
    • 某些组件使用:放在他们共同的父组件state中(官方称此操作为:状态提升>
  • 关于父子之间通信:

    • 【父组件】给【子组件】传递数据:通过props传递
    • 【子组件】给【父组件】传递数据:通过props传递,要求父提前给子传递一个函数
  • 注意defaultchecked 和 checked的区别,类似的还有: defaultValue和 value

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

文件夹结构

因为关注的是react的学习,所以懒得写less文件修饰了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nR9T0ypk-1652255785368)(C:\Users\12274\AppData\Roaming\Typora\typora-user-images\image-20220506233638382.png)]

App.js

import Header from './components/Header';
import List from './components/List'
import Footer from './components/Footer';
import './App.less';
import React, {Component} from 'react';

class App extends Component {
  state = {
      todos:[
          {id:'001',name:'吃饭',done:true},
          {id:'002',name:'啪啪',done:true},
          {id:'003',name:'睡觉',done:false},
      ]
  }
  addTodo = (val) =>{
    console.log(val)
    const {todos} = this.state
    const newTodos = [val,...todos]
    this.setState({
      todos:newTodos
    })
  }
  changeTodo = (id,done)=>{
    const {todos} = this.state
    const newTodos = todos.map((item) =>{
      if(item.id === id) return {...item,done}
      else return item
    })
    this.setState({
      todos:newTodos
    })
  }
  deleteTodo = (id)=>{
    const {todos} = this.state
    //删除指定id的todo
    const newTodos = todos.filter((item)=>{
      return item.id !== id
    })
    this.setState({
      todos:newTodos
    })
  }
  checkAllTodo = (state)=>{
    const {todos} = this.state
    const newTodos = todos.map((item)=>{
      return {...item,done:state}
    })
    this.setState({
      todos:newTodos
    })
  }
  clearAllDone = ()=>{
    const {todos} = this.state
    const newTodos = todos.filter((item)=>{
      return item.done === false
    })
    this.setState({
      todos:newTodos
    })
  }
  render(){
    const {todos} = this.state
    return (
      <div className="App">
        <Header addTodo={this.addTodo}/>
        <List changeTodo={this.changeTodo} todos={todos} deleteTodo={this.deleteTodo}/>
        <Footer todos={todos} checkAllTodo={this.checkAllTodo} clearAllDone={this.clearAllDone}/>
      </div>
    );
  }
}

export default App;

Header.jsx

import React,{Component} from "react";
import PropTypes from 'prop-types'

export default class Header extends Component {
    static propTypes = {
        addTodo:PropTypes.func.isRequired
    }

    handleKeyUp = (event) =>{
        const {keyCode,target} = event
        if(keyCode !== 13) return;
        console.log(target.value)
        if(target.value.trim() === true) alert('不能为空')
        let todoObj = {
            id: Date.now(),
            name:target.value,
            done:false
        }
        this.props.addTodo(todoObj)
    }
    render(){
        return(
            <div>
                <input type="text" onKeyUp={this.handleKeyUp} />
            </div>
        )
    }
}

List.jsx

import React,{Component} from "react";
import Item from "../item";
import PropTypes from 'prop-types'

export default class List extends Component {
    static propTypes = {
        changeTodo:PropTypes.func.isRequired,
    }
    render(){
        const {todos,changeTodo,deleteTodo} = this.props
        console.log(changeTodo)
        return(
            <div>
                <ul>
                    {
                        todos.map((item)=>{
                            return <Item  key={item.id} {...item} changeTodo={changeTodo} deleteTodo={deleteTodo}/>
                        })
                    }
                </ul>
            </div>
        )
    }
}

Item.jsx

import React,{Component} from "react";

export default class Item extends Component {
    handleCheck = (id) =>{
        return (event)=>{
            console.log(this.props)
            this.props.changeTodo(id,event.target.checked)
        }
    }
    handleDelete = (id) =>{
        this.props.deleteTodo(id)
    }
    render(){
        const {id,name,done} = this.props
        return(
            <li>
                <label htmlFor="">
                    <input onChange={this.handleCheck(id)} checked={done} type="checkbox"/>
                    <span>{name}</span>
                </label>
                <button onClick={()=>{this.handleDelete(id)}}>删除</button>
            </li>
        )
    }
}

Footer.jsx

import React, { Component } from "react";

export default class Footer extends Component {
    handleCheckAll = (event)=>{
        this.props.checkAllTodo(event.target.checked)
    }
    handleDeleteAll = ()=>{
        this.props.clearAllDone()
    }
    render(){
        const {todos} = this.props
        //已完成的个数
        const doneCount = todos.filter(item=>{
            return item.done === true
        }).length
        //总数
        const total = todos.length
        return(
            <div>
                <label htmlFor="">
                    <input type="checkbox" onChange={this.handleCheckAll} checked={doneCount === total&&total !== 0 ? true : false}  name="" id="" />
                </label>
                <span>
                    <span>已完成{doneCount}</span> / 全部{total}
                </span>
                <button onClick={this.handleDeleteAll}>清楚已完成任务</button>
            </div>
        )
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

PrototypeONE

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值