美文网首页
react案例todoList

react案例todoList

作者: 回不去的那些时光 | 来源:发表于2019-10-14 21:54 被阅读0次

项目结构

|- app.js
|- app.css
|-
    |components
        |- Foot.js
        |- Head.js
        |- Item.js
        |- List.js

效果图

image.png

app.js

import React, { Component } from 'react';
import './App.css';
import Foot from './components/Foot'
import Head from './components/Head'
import List from './components/List'

class App extends Component {
    constructor(props) {
        super(props)
        this.state = {
            todos: [
                { id: 1, title: '看1小时电影', finished: false },
                { id: 2, title: '看2小时电影', finished: false },
                { id: 3, title: '看3小时电影', finished: false },
                { id: 4, title: '看4小时电影', finished: false },
                { id: 5, title: '看5小时电影', finished: false },
                { id: 6, title: '看6小时电影', finished: false }
            ],
            finishedCount: 0
        }
    }

    // 修改完成状态
    _changeTodoFinished = (todoId, isFinished) => {
        const tempTodos = this.state.todos;
        let finishedCount = 0;
        // 1、遍历
        tempTodos.forEach((todo, index) => {
            if (todoId === todo.id) {
                todo.finished = isFinished;
            }
            if (todo.finished) {
                finishedCount += 1;
            }
        })

        this.setState({
            todos: tempTodos,
            finishedCount
        })
    }

    // 删除一条记录
    _removeTodoWithId = (todoId) => {
        const tempTodos = this.state.todos;
        let finishedCount = 0;
        // 1、遍历
        tempTodos.forEach((todo, index) => {
            if (todoId === todo.id) {
                tempTodos.splice(index, 1)
            }
        })

        // 2、处理选中的
        tempTodos.forEach((todo, index) => {
            if (todo.finished) {
                finishedCount += 1;
            }
        })

        // 更新状态
        this.setState({
            todos: tempTodos,
            finishedCount
        })
    }

    // 添加一条记录
    _addOneTodo = (todo) => {
        let tempTodos = this.state.todos;
        tempTodos.push(todo);
        this.setState({
            todos: tempTodos
        })
    }

    // 删除已完成的任务
    _delCheckedTodo = () => {
        let tempTodos = this.state.todos;
        let tempArr = [];
        tempTodos.forEach((todo) => {
            if (!todo.finished) {
                tempArr.push(todo);
            }
        })

        this.setState({
            todos: tempArr,
            finishedCount: 0
        })
    }

    // 选中/取消所有
    _delSelectedAllTodo =(flag) => {
        const tempTodos = this.state.todos;
        let finishedCount = 0;
        tempTodos.forEach((todo, index) => {
            todo.finished = flag;
        })

        tempTodos.forEach((todo, index) => {
            if (todo.finished) {
                finishedCount += 1;
            }
        })

        this.setState({
            todos: tempTodos,
            finishedCount
        })
    }

    render() {
        const { todos, finishedCount } = this.state;
        return (
            <div className="App" >
                { /* 头部 */}
                <Head
                    lastTodoId={todos.length === 0 ? 0 : todos[todos.length - 1].id}
                    addOneTodo={this._addOneTodo}
                />
                { /* 列表 */}
                <List
                    todos={todos}
                    removeTodoWithId={this._removeTodoWithId}
                    changeTodoFinished={this._changeTodoFinished}
                />
                { /* 底部 */}
                <Foot
                    finishedCount={finishedCount}
                    totalCount={todos.length}
                    delCheckedTodo={this._delCheckedTodo}
                    delSelectedAllTodo={this._delSelectedAllTodo}
                />
            </div>
        )
    }

}

export default App;

app.css

.App {
  width: 400px;
  padding: 10px;
  margin: 10px auto;
  border: 1px solid #ccc;
}

.todos-item {
  display: flex
}
.todos-item-title {
  display: inline-block;
  flex: 1;
}

Foot.js

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

export default class Foot extends Component {
    static propTypes = {
        finishedCount: PropTypes.number.isRequired,  // 完成数量
        totalCount: PropTypes.number.isRequired,  // 总数量
        delCheckedTodo: PropTypes.func.isRequired,  // 删除已经完成的任务
        delSelectedAllTodo: PropTypes.func.isRequired  // 选中/取消所有
    }

    render() {
        const { finishedCount, totalCount, delCheckedTodo, delSelectedAllTodo } = this.props;
        return (
            <div style={{ paddingLeft: "40px" }}>
                <label>
                    <input type="checkbox"
                        checked={finishedCount === totalCount}
                        onChange={() => delSelectedAllTodo(finishedCount !== totalCount)} />
                    <span>已完成{finishedCount}件</span>/
                    <span>总计{totalCount}件</span>
                </label>
                <button
                    style={{ float: 'right' }}
                    onClick={() => delCheckedTodo()}>清空已完成任务</button>
            </div>
        )
    }
}

Head.js

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

export default class Head extends Component {
    constructor(props) {
        super(props)
        // 绑定ref
        this.myInput = React.createRef();
    }

    static propTypes = {
        lastTodoId: PropTypes.number.isRequired,  // 最后一条记录的Id
        addOneTodo: PropTypes.func.isRequired     // 添加一条记录
    }

    render() {
        return (
            <div>
                <input ref={this.myInput}
                    placeholder="请输入今天的任务清单,按回车键保存"
                    style={{ width: '100%' }}
                    onKeyDown={(e) => this._handleEvent(e)}
                />
            </div>
        )
    }

    _handleEvent = (e) => {
        // console.log(e.keyCode);
        const { lastTodoId, addOneTodo } = this.props;
        // 判断是否是回车键
        if (13 === e.keyCode) {
            // 判断输入的内容是否为空
            if (!this.myInput.current.value.trim()) {
                alert("输入的内容不能为空!");
                return;
            }
            // 创建todo对象
            const todo = { id: lastTodoId + 1, title: this.myInput.current.value, finished: false };
            addOneTodo(todo);
            // 清空
            this.myInput.current.value = "";
        }
    }
}

Item.js

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

export default class Item extends Component {
    constructor(props) {
        super(props)
        this.state = {
            showDelBtn: false
        }
    }
    static propTypes = {
        todo: PropTypes.object.isRequired,  // 单条数据
        removeTodoWithId: PropTypes.func.isRequired,  // 方法
        changeTodoFinished: PropTypes.func.isRequired // 选中方法
    }


    render() {
        const { todo, removeTodoWithId, changeTodoFinished } = this.props;
        const { showDelBtn } = this.state;
        return (
            <li
                className="todos-item"
                onMouseOver={() => this._showBtn(true)}
                onMouseOut={() => this._showBtn(false)}
            >
                <label className="todos-item-title">
                    <input type="checkbox" checked={todo.finished} onChange={() => changeTodoFinished(todo.id, !todo.finished)} />
                    <span>{todo.title}</span>
                </label>
                <button onClick={() => removeTodoWithId(todo.id)} style={{ display: showDelBtn ? 'inline-block' : 'none' }}>删 除</button>
            </li>
        )
    }

    // 处理按钮显示隐藏
    _showBtn(flag) {
        this.setState({
            showDelBtn: flag
        })
    }
}

List.js

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

export default class List extends Component {
    static propTypes = {
        todos: PropTypes.array.isRequired,  // 数据数组
        removeTodoWithId: PropTypes.func.isRequired,  // 删除方法
        changeTodoFinished: PropTypes.func.isRequired // 选中方法
    };

    render() {
        const { todos, removeTodoWithId, changeTodoFinished } = this.props;
        return (
            <ul>
                {
                    todos.map((todo, index) => (
                        <Item
                            key={index}
                            todo={todo} 
                            removeTodoWithId={removeTodoWithId}
                            changeTodoFinished={changeTodoFinished}
                        />
                    ))
                }
            </ul>
        )
    }
}

相关文章

网友评论

      本文标题:react案例todoList

      本文链接:https://www.haomeiwen.com/subject/fmvdmctx.html