React 小案例 – todos

react 脚手架 todos 练手小项目分享
注意红框中的文件,其中 01_脚手架自带文件02_x 不用理会,忽略就好

image.png


// App.js
import React, { Component } from 'react'

import Header from './components/Header'
import Footer from './components/Footer'
import List from './components/List'

export default class App extends Component {
    constructor(props){
        super(props);

        this.state = {
            todos:[
                {
                    id:"001",
                    todo:"睡觉",
                    done:true
                },
                {
                    id:"002",
                    todo:"吃饭",
                    done:true
                },
                {
                    id:"003",
                    todo:"看书",
                    done:false
                }
            ]
        }
    }

    updateTodos = () => {
       return (todoObj) => {
            const todos = [todoObj,...this.state.todos];
            this.setState({todos});
       }
    }

    handleChange = (id,done) => {
       const {todos} = this.state;
       const newTodos = todos.map(todo => {
           if(todo.id === id) return {...todo,done:done}
           else return todo
       })
       this.setState({todos:newTodos})
    }

    handleDelete = (id) => {
        const {todos} = this.state;
        const newTodos = todos.filter((todo) => {
            return todo.id !== id;
        })

        this.setState({todos:newTodos});
    }

    handleCheckedAll = (done) => {
        const {todos} = this.state;
        const newTodos = todos.map(todo => {
            return {...todo,done}
        })

        this.setState({todos:newTodos})
    }

    handleDeleteAll = () => {
        const {todos} = this.state;
        const newTodos = todos.filter(todo => {
            return todo.done === false;
        })

        this.setState({todos:newTodos})
    }


    render() {
        const {todos} = this.state;
        return (
            <div className="container">
                <Header updateTodos={this.updateTodos()}/>
                <List todos={todos} handleChange = {this.handleChange} handleDelete = {this.handleDelete}/>
                <Footer todos={todos} handleCheckedAll = {this.handleCheckedAll} handleDeleteAll = {this.handleDeleteAll}/>
            </div>
        )
    }
}
复制代码

// Header.jsx
import React, { Component } from 'react'
import {nanoid} from 'nanoid'

export default class Header extends Component {

    addItem = (event) => {
        let {updateTodos} = this.props;
        let todoObj = {
            id:nanoid(),
            todo:event.target.value,
            done:false
        }
        if(event.keyCode === 13){
            updateTodos(todoObj);
            event.target.value = "";
        }
    }

    render() {
        return (
            <div className="header">
                <input type="text" placeholder="请输入内容,按回车键确认" onKeyUp={this.addItem}/>
            </div>
        )
    }
}
复制代码

// List.jsx
import React, { Component } from 'react'
import PropTypes from 'prop-types'

import Item from '../Item'

export default class List extends Component {

    static ropTypes = {
        handleChange:PropTypes.func.isRequired,
        todos:PropTypes.array.isRequired
    }

    render() {
        const {todos,handleChange,handleDelete} = this.props;
        return (
            <ul className="list-container">
                {todos.map(todo=>{
                    return <Item {...todo} key={todo.id} handleChange={handleChange} handleDelete = {handleDelete}/>
                })}
            </ul>
        )
    }
}
复制代码

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

export default class Item extends Component {

    static propTypes = {
        handleChange:PropTypes.func.isRequired
    }

    deleteItem = (id) => {
        console.log("被删除的id是",id);
        if(window.confirm("确定删除吗?")){
            this.props.handleDelete(id);
        }
    }

    handleChange = (id) => {
        const {handleChange} = this.props;
        return (event) => {
            handleChange(id,event.target.checked);
        }
    }

    render() {
        const {id,todo,done} = this.props;
        return (
            <li className="list-item">
                <input type="checkbox" checked={done} onChange={this.handleChange(id)} /> 
                <span>{todo}</span> 
                <button onClick={()=>{this.deleteItem(id)}}>删除</button> {/* 这里没有使用高阶函数,就直接写成了这样的 */}
            </li>
        )
    }
}

复制代码

// Footer.jsx
import React, { Component } from 'react'

export default class Footer extends Component {

    deleteAll = ()=>{
        this.props.handleDeleteAll();
    }

    checkedAll = (event) => {
        this.props.handleCheckedAll(event.target.checked);
    }

    render() {
        const {todos} = this.props;
        const total = todos.length;

        const doneCount = todos.reduce((pre,current)=>{
            return pre + (current.done === true ? 1 : 0);
        },0)

        return (
            <div className="footer">
                <input type="checkbox" checked={doneCount === total && total !== 0 ? true:false} onChange={this.checkedAll}/>
                <span>{doneCount}完成/全部{total}</span>
                <button onClick={this.deleteAll}>清除已完成项目</button>
            </div>
        )
    }
}

复制代码

最终的成品

image.png

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享