菜鸟花了一个月,做出一个过得去的ToDoList

212 阅读3分钟

记录一下这个特殊的日子,2020年下半年开始接触React。
这学期开学,老师让我做出点东西给他看,因为只一味地看书是完全不会有进步的,没有自己敲代码出点错误是不会得到进步的。
(优秀的程序猿都是在不断debug中得到成长的,所谓代码一年debug10年就是这样的吧)。
在和老师的一次次交流下,程序一步步变得规范,代码量一步步减少,各种各样的bug也出了,不过最后在秃头日常中,还是对付了过来。

也确实有了很大的收获提升了对React的兴趣,将这段经历分享给是小白的你,咱们共同进步,大佬请自动忽略一个菜鸟的自白,谢谢~。
不摆龙门阵了,接下来进入正题吧。

最终效果展示如下:
可实现删除、添加和完成的基本功能,同时能展示网页刷新时添加事项的时间。
最终效果展示在这里插入图片描述
项目目录结构,TodoList是父组件,TOdoListItem是子组件,总共就分为两个组件。
TodoList部分:

import React, { Component } from 'react';
import TodoListItem from './TodoListItem';
import { getUuid } from './getUuid.js';
import { handleNowTime } from './getTIME';

import './index.css';
const STATUS_ITEM = 0;

class TodoList extends Component {
  constructor(props) {
    super(props);
    this.state = {
      list: [{
        content: "睡觉",
        status: STATUS_ITEM,
        startTime: handleNowTime(new Date()),
        uuid: getUuid()
      },
      {
        content: "做作业",
        status: STATUS_ITEM,
        startTime: handleNowTime(new Date()),
        uuid: getUuid()

      }, {
        content: "学习",
        status: STATUS_ITEM,
        startTime: handleNowTime(new Date()),
        uuid: getUuid()
      }, {
        content: "基于B/S开发的一站式班级管理系统和代码评测系统",
        status: 0,
        startTime: handleNowTime(new Date()),
        uuid: getUuid()
      }
      ],
      finished: 0,
      inputValue: ''
    };
  }
  handleChangeValue = (event) => {
    const { value } = event.target;
    this.setState({
      inputValue: value
    });
  }

  handleAddTask = () => {
    const { inputValue } = this.state;
    if (!inputValue) {
      alert("输入为空,请重新输入待办事项");
      return;
    }
    let nowTime = new Date();
    const startTime = handleNowTime(nowTime);
    let Uuid = getUuid();
    var obj = {
      content: inputValue,
      status: STATUS_ITEM,
      startTime: startTime,
      uuid: Uuid
    };
    const { list } = this.state;
    list.push(obj);
    this.setState({
      list,
      inputValue: ''
    });
  }
  // 更新已完成的事项
  updateFinished = () => {
    const { list } = this.state;
    let finishedTask = 0;
    list.forEach((item) => {
      if (item.status === !STATUS_ITEM) {
        ++finishedTask;
      }
    });
    this.setState({
      finished: finishedTask
    });
  }

  handleClickDelete = (Uuid) => {
    const { list } = this.state;
    const List = list.filter(item =>
      item.uuid !== Uuid);
    this.setState({
      list: List
    });
  }
  enterPress = (event) => {
    if (event.key === 'Enter') {
      this.handleAddTask();
      event.target.value = ''
    }
  }

  render() {
    const { list } = this.state;
    const { finished } = this.state;
    const { inputValue } = this.state;
    return (
      <div className="container">
        <h1>TO DO LIST</h1>
        <hr></hr>
        <div className="listItem">
          <TodoListItem
            list={list}
            handleClickDelete={this.handleClickDelete}
            updateFinished={this.updateFinished}
          />
          <div className="item-count">
            {finished}
            已完成任务/
            {list.length}
            任务总数
          </div>
          <div className="addItem">
            <input
              className="add-input"
              type="text"
              placeholder="Add your item……"
              onKeyPress={this.enterPress}
              value={inputValue}
              onChange={this.handleChangeValue}
            />
            <button className="addButton"
              onClick={this.handleAddTask}
            >
              添加
          </button>
          </div>

        </div>
      </div>
    );
  }
}

export default TodoList;

TodoListItem部分:

import React, { Component } from 'react';

const STATUS_ITEM = 0;
class TodoListItem extends Component {
    constructor(props) {
        super(props);
        this.state = {}
    }
    updateFinished() {
        this.props.updateFinished();
    }
    // 删除任务
    handleClickDelete(Uuid) {
        this.props.handleClickDelete(Uuid);
    }
    // 点击完成事件
    handleClickFinished = (Uuid) => {
        const obj = [];
        const { list } = this.props;
        list.forEach((item) => {
            if (item.uuid === Uuid) {
                if (item.status === STATUS_ITEM) {
                    item.status = !STATUS_ITEM;
                } else {
                    item.status = STATUS_ITEM;
                }
                this.updateFinished();
                this.setState({
                    list: obj
                });
            }
            else {
                obj.push(item);
            }
        })
    }
    listMapItem = (item) => {
        return (
            <div className="warpper"
                key={item.uuid}
            >
                <div className="item">
                    <input type="checkbox"
                        defaultChecked={item.status}
                        onClick={this.handleClickFinished.bind(this, item.uuid)}
                    />
                    <span
                        style={{ textDecorationLine: item.status === STATUS_ITEM ? 'none' : 'line-through' }}
                    >{item.content}
                    </span>
                </div>

                <div className="startTime">
                    {item.startTime}
                </div>
                <button
                    className="delete-button "
                    onClick={this.handleClickDelete.bind(this, item.uuid)}
                >
                    删除
                    </button>
            </div>
        );
    }
    listMap = () => {
        const { list = [] } = this.props;
        return (
            list.map(item => {
                return (this.listMapItem(item))
            })
        )
    }
    render() {
        return (
            <div>
                {this.listMap()}
            </div>
        );
    }
}

export default TodoListItem;

开发日志:
在这里插入图片描述

  • 利用flex布局,尽量少用px单位
  • 改变函数命名模式,使用驼峰命名标准
  • 理清数据流的转态,画图来分析
  • 让代码尽量简洁
  • 尽可能使用箭头函数(需要传参除外,这又是好大一个bug,后来改了)
  • 父子组件里的东西不能乱写
  • render里面的东西更简洁一点,这样利于以后的维护和修改,我的render如此简单
    render() { return ( <div> {this.listMap()} </div> ); }
  • 公共函数应该写在组件外,而不是组件内,增加代码的可移植性和可复用性,减少删改的次数
  • 使用枚举来表示事项状态,不然以后自己都不知道status=0表示什么意思(枚举类型应该使用大写)const STATUS_ITEM = 0;

差不多这些,接下来干DvaJs去了,才有提升……
未完待续……