用React实现一个完整的TodoList的示例代码


Posted in Javascript onOctober 30, 2017

前言:算起来已经有一个多月没有写博客了,近来懈怠了不少,也不知道要写些什么,最近学了一段时间的React,一直都在看些理论性的知识,总觉得应该写个什么来练练手,所以还是拿个简单的todoList来举个例子吧!

一. 首先根据效果图讲一下要实现的功能吧

用React实现一个完整的TodoList的示例代码

todoList最终效果图

(1)可以添加任务;
(2)已完成任务以及未完成任务的颜色区分开;
(3)进行添加任务,修改任务状态,以及删除任务时,下面的任务完成数目和任务总数要进行变化;

以上就是要实现的功能。

二. 接下来该如何设计呢?

(1)任务存储的数据结构:

list: [{
      id: 0,
      name: '吃饭',
      status: 0
    }, {
      id: 1,
      name: '睡觉',
      status: 0
    }, {
      id: 2,
      name: '打豆豆',
      status : 0
    }]

每个任务都有自己的id,任务名,以及任务的状态,任务的id除了标识任务的唯一性,还可以作为列表项的key值。我们都知道在react中使用列表,列表的每一项必须有个key值,这样会使得每个列表项可以快速定位,在执行Diff算法时减少不必要的查询,从而对性能的提升有所帮助。

(2)组件的划分

  1. TodoList整体作为一个大组件;
  2. 列表中的每个列表项(ListItem)作为一个组件;
  3. 任务的添加框(Dialog)作为一组件。

三. 具体实现

以列表项ListItem的实现为例:

将列表项单独划分为一个组件是必须的,这样使得每个单独的条目都是独立的,使得代码的逻辑更加简单,增强代码的复用性,维护也会变得更简单。

当然聪明的你肯定会想到一个问题:每一个Task的状态改变或者Task的添加删除,Task的完成数目和总数目都是会改变的,可是每个ListItem都是相互独立的,如何实现呢?这时就要用到父子组件之间的通信了。

如果你也是和我一样React的初学者,百度一下就会出现很多文章都会讲父子组件间如何通信,下面我简单说一下自己简单粗暴的理解:

在父子组件中定义改变state数据的方法,将方法以props的形式传递给子组件,在子组件中触发事件处理程序,然后满足某种条件的话就执行父组件传来的函数。

具体代码如下:

父组件中的代码:

import React, { Component } from 'react';
import ListItem from './listItem';
import Dialog from './dialog';
import './main.css';

class TodoList extends Component {
  constructor (props) {
    super(props);
    
    //初始任务列表
    this.state = {
      list: [{
        id: 0,
        name: '吃饭',
        status: 0
      }, {
        id: 1,
        name: '睡觉',
        status: 0
      }, {
        id: 2,
        name: '打豆豆',
        status : 0
      }],
      finished: 0
    };
  }
  
  //添加新任务,在组件中以props的形式传递给子组件
  addTask (newitem) {
    var allTask = this.state.list;
    allTask.push(newitem);
    this.setState({
      list: allTask
    });
  }
  //更新完成的任务,在组件中以props的形式传递给子组件
  updateFinished (todoItem) {
    var sum = 0;
    this.state.list.forEach( (item) => {
      if (item.id === todoItem.id) {
        item.status = todoItem.status;
      }
      if (item.status === 1) {
        sum++;
      }
    });
    this.setState({
      finished: sum
    });
  }

  //更新任务总数,在组件中以props的形式传递给子组件
  updateTotal (todoItem) {
    var obj = [], sum = 0;
    this.state.list.forEach((item) => {
      if (item.id !== todoItem.id) {
        obj.push(item);
        if (item.status === 1 ) {
          sum++;
        }
      }
    });
    this.setState({
      list: obj,
      finished: sum
    });
  }

  render () {
    return (
      <div className="container">
        <h1>TodoList</h1>
        <ul>
          { this.state.list.map ((item, index) =>
            <ListItem 
              item={item} 
              finishedChange={this.updateFinished.bind(this)} 
              totalChange={this.updateTotal.bind(this)}
              key={index}
            />
          )}
          <li>{this.state.finished}已完成 / {this.state.list.length}总数</li>
        </ul>
        <Dialog addNewTask={this.addTask.bind(this)} nums={this.state.list.length}/>
      </div>
    );
  }
}

export default TodoList;

子组件中的代码:

import React, { Component } from 'react';

class ListItem extends Component {
  constructor (props) {
    super(props);

    this.handleFinished = this.handleFinished.bind(this);
    this.handleDelete = this.handleDelete.bind(this);
  } 

  handleFinished () {
    var status = this.props.item.status;

    status = (status === 0 ? 1 : 0);

    var obj = {
      id: this.props.item.id,
      name: this.props.item.name,
      status: status
    }
    
    this.props.finishedChange(obj); //执行父组件传来的方法
  }

  handleDelete () {
    this.props.totalChange(this.props.item); //执行父组件传来的方法
  }

  render () {
    const item = this.props.item;

    const unfinish = {
      backgroundColor: '#DFFCB5',
      color: '#2EB872',
    };

    const finish = {
      backgroundColor: '#FFFA9D',
      color: '#FF9A3C',
      textDecoration: 'line-through'
    }

    var itemStyle = item.status === 0 ? unfinish : finish;
    
    return (
      <li key={item.id} style={itemStyle}>
        <span 
          onClick={this.handleFinished} 
          id={item.id}
          className="check-btn"
          style={{backgroundColor: item.status === 0 ? '#fff' : '#A1EAFB'}}
        ></span>
        <span>{ item.name }</span>
        <span onClick={this.handleDelete} className="delete-btn">删除</span>
      </li>
    );
  }
}

export default ListItem;

以上是对这个小练习的一个总结,如果你也和我一样是个react新手的话,写完这个相信你对React一定会有更近一步的理解,小练习以上传至github,可以进行参考哦!希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
如何让div span等元素能响应键盘事件操作指南
Nov 13 Javascript
js检测判断日期大于多少天的方法
May 04 Javascript
jquery实现加载进度条提示效果
Nov 23 Javascript
微信小程序 for 循环详解
Oct 09 Javascript
vue.js初学入门教程(1)
Nov 03 Javascript
Vuex之理解state的用法实例
Apr 19 Javascript
关于echarts在节点显示动态数据及添加提示文本所遇到的问题
Apr 20 Javascript
详解React Native 屏幕适配(炒鸡简单的方法)
Jun 11 Javascript
js监听html页面的上下滚动事件方法
Sep 11 Javascript
javascript中数组的常用算法深入分析
Mar 12 Javascript
vue 设置 input 为不可以编辑的实现方法
Sep 19 Javascript
详细分析Node.js 多进程
Jun 22 Javascript
JavaScript实现精美个性导航栏筋斗云效果
Oct 29 #Javascript
vue中的scope使用详解
Oct 29 #Javascript
Vue.js划分组件的方法
Oct 29 #Javascript
vue.js  父向子组件传参的实例代码
Oct 29 #Javascript
vue.js todolist实现代码
Oct 29 #Javascript
javascript按钮禁用和启用的效果实例代码
Oct 29 #Javascript
jQuery实现切换隐藏与显示同时切换图标功能
Oct 29 #jQuery
You might like
php中的时间显示
2007/01/18 PHP
PHP正则提取不包含指定网址的图片地址的例子
2014/04/21 PHP
php设置静态内容缓存时间的方法
2014/12/01 PHP
PHP正则表达式笔记与实例详解
2019/05/09 PHP
关于JavaScript的gzip静态压缩方法
2007/01/05 Javascript
与jquery serializeArray()一起使用的函数,主要来方便提交表单
2011/01/31 Javascript
js限制文本框只能输入数字(正则表达式)
2012/07/15 Javascript
异步动态加载js与css文件的js代码
2013/09/15 Javascript
javascript 数字格式化输出的实现代码
2013/12/10 Javascript
JS实现的通用表单验证插件完整实例
2015/08/20 Javascript
JavaScript String 对象常用方法总结
2016/04/28 Javascript
HTML页面定时跳转方法解析(2种任选)
2016/12/22 Javascript
JS原生数据双向绑定实现代码
2017/08/14 Javascript
JavaScript中Hoisting详解 (变量提升与函数声明提升)
2017/08/18 Javascript
React Native 图片查看组件的方法
2018/03/01 Javascript
在vue中使用回调函数,this调用无效的解决
2020/08/11 Javascript
Python实现windows下模拟按键和鼠标点击的方法
2015/03/13 Python
Python中的id()函数指的什么
2017/10/17 Python
opencv实现静态手势识别 opencv实现剪刀石头布游戏
2019/01/22 Python
Django框架设置cookies与获取cookies操作详解
2019/05/27 Python
python定义类的简单用法
2020/07/24 Python
python环境搭建和pycharm的安装配置及汉化详细教程(零基础小白版)
2020/08/19 Python
Python 微信公众号文章爬取的示例代码
2020/11/30 Python
CSS3中利用animation属性创建雪花飘落特效
2014/05/14 HTML / CSS
Hotter Shoes英国官网:英伦风格,舒适的鞋子
2017/12/28 全球购物
市场营销专业推荐信
2013/11/03 职场文书
测控技术与通信工程毕业生自荐信范文
2013/12/28 职场文书
工作室成员个人发展规划范文
2014/01/24 职场文书
护理专业大学生自我推荐信
2014/01/25 职场文书
《中华少年》教学反思
2014/02/15 职场文书
《鱼游到了纸上》教学反思
2014/02/20 职场文书
高中生的自我评价
2014/03/04 职场文书
个人承诺书
2014/03/26 职场文书
2015年党员个人工作总结
2015/05/13 职场文书
小学生作文写作技巧100例,非常实用!
2019/07/08 职场文书
JAVA 线程池(池化技术)的实现原理
2022/04/28 Java/Android