热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

react的小实例todolist

一构建开发环境   todolist的开发工具包为webpack+es6+react,首先需要构建开发环境,我在上一篇文章webpack构建ant-design中已经构建了ant-design的开发环境,这里也是用到这边文章中所用的环境,在这个实例中需要用到箭头函数,所以还需要安装一下 stage-0,安装语句如下:npminstall--save-devba

一构建开发环境

      todolist的开发工具包为webpack+es6+react,首先需要构建开发环境,我在上一篇文章webpack构建ant-design中已经构建了ant-design的开发环境,这里也是用到这边文章中所用的环境,在这个实例中需要用到箭头函数,所以还需要安装一下 stage-0,安装语句如下:

npm install --save-dev babel-preset-stage-0

 修改.babelrc文件如下

{
  "presets": [
    "es2015",
    "react",
    "stage-0"
  ],
  "sourceMaps": true
}

 二分析todolist结构

      react的小实例todolist

完成版的todolist如上图所示,按照react组件化编程的风格,我大致将todolist分为三个组件,分别是TodoHeader,用来输入任务名称,TodoMain,用来展示任务,TodoFooter,用来全选和清楚选中的任务,我创建的文件,及问价目录如下

react的小实例todolist

三 输入,存储任务

  index.js作为webpack打包的入口文件,App作为主要的组件来引用上面三个组件。

 index.js

require("./style/index.less");
import ReactDom from 'react-dom';
import React from 'react';
import App from '../src/component/App';
ReactDom.render(, document.getElementById('root'));

 App.jsimport React from 'react';import TodoHeader from './TodoHeader';

import TodoMain from './TodoMain';
import TodoFooter from './TodoFooter';
class App extends React.Component{
    constructor(props){
        super(props);
        this.db = localStorage; //定义一个localStorage容易
        let todos = this.db.getItem('todos') || []; //通过键todos,来获取localStorage容器中的值
        this.state = {
            todos: eval('(' + todos + ')'),
            isAllChecked: false //用来表示是否全选
        };
    }
    componentDidMount(){
       // let todos = eval('(' + this.state.todos + ')');
       // if(todos.length > 0){
       //     this.setState({todos: todos});
       // }
    }
    allChecked() {
//全选函数,供子组件调用 let isAllChecked = false;
// every() 方法用于检测数组所有元素是否都符合指定条件(通过函数提供)。
if(this.state.todos.every((todo) => todo.isDone)){ isAllChecked = true; } this.setState({ todos: this.state.todos, isAllChecked: isAllChecked }) } clearDOne= () =>{
//清除选中的项目 let todos = this.state.todos.filter(todo => !todo.isDone); //过滤没有选中的项目 this.setState({ todos: todos, isAllChecked: false, }); this.db.setItem('todos', JSON.stringify(todos)); //修改localStorage中键todos的值,以json数组的形式存储,方便后续取出操作 } addTodo =(todoItem) =>{
//添加项目操作 this.state.todos.push(todoItem);//todo列表 ,向todos数组中插入一条记录 this.db.setItem('todos', JSON.stringify(this.state.todos)); //将所有的记录再次保存如localStorage中 this.allChecked(); } deleteTodo = (index) =>{
//删除一个项目 this.state.todos.splice(index, 1);//通过传过来的索引值,删除数组中的一条记录 this.setState({todos: this.state.todos}); // this.db.setItem('todos', JSON.stringify(this.state.todos));//将更新的todos数组,插入到localStorage中 } changeTodoState = (index, isDone, isChangeAll = false) => { // 改变任务状态,传递给TodoItem和Footer组件的方法 if(isChangeAll){ this.setState({ todos: this.state.todos.map( (todo) =>{ todo.isDOne= isDone; return todo; }),isAllChecked: isDone }) }else{ this.state.todos[index].isDOne= isDone; this.allChecked(); } this.db.setItem('todos', JSON.stringify(this.state.todos)); } render(){ let info = { isAllChecked: this.state.isAllChecked, todoCount: this.state.todos.length || 0, todoDoneCount: (this.state.todos && this.state.todos.filter((todo) => todo.isDone)).length || 0 }; return(
); } } export default App;

  在HTML5中,新加入了一个localStorage特性,这个特性主要是用来作为本地存储来使用的,解决了COOKIE存储空间不足的问题(COOKIE中每条COOKIE的存储空间为4k),localStorage中一般浏览器支持的是5M大小,这个在不同的浏览器中localStorage会有所不同。

三组件TodoHeader

 ,组件TodoHeader的代码如下,用户在输入框中输入,点击回车按钮,保存用户的输入到localStorage中去。

import React from 'react';
class TodoHeader extends React.Component{
    constructor(props){
        super(props);
        this.state = {

        };
        this.handlerKeyUp = this.handlerKeyUp.bind(this); //绑定键盘事件,也可以使用箭头函数
    }
    componentDidMount(){

    }
    handlerKeyUp(e){
        //鼠标回车事件
        if(e.keyCode == 13){
            //键盘敲击回车时间
            let value = e.target.value; //获取输入框中输入的值
            if(!value) return false; //如果输入框没有输入,则返回false
            let newTodoItem = {
                text: value,
                isDone: false
            };//将输入的值保存在一个对象中
            e.target.value = '';//将输入框的值置空
            this.props.addTodo(newTodoItem) //调用父组件的方法,通过this.props调用父控件的方法,将输入的值传递给父控件,在父控件中对state的值进行修改,从而重新渲染页面。
        }
    }
    render() {
        return(
            

React Todo

) } }; export default TodoHeader;

  四 展示组件TodoMain

 定义一个组件TodoItem,来处理具体某一条的记录,然后再TodoMain中来处理出所有的数据

TodoItem.js代码如下

   

import React from 'react';
export default class TodoItem extends React.Component{
    constructor(props){
        super(props);
        this.state = {
           isShow: false,
        };
    }
    componentDidMount(){

    }
    handlerChange =()=>{
//多选框处理事件,选中则表示已处理 let isDOne= !this.props.isDone; this.props.changeTodoState(this.props.index, isDone); } handlerDelete =()=>{
//删除事件 this.props.deleteTodo(this.props.index); } handlerMouseOver =()=>{
//鼠标移入事件 this.setState({isShow:true}); } handlerMouseOut =() =>{
//鼠标移出事件 this.setState({isShow:false}); } render(){ let className = this.props.isDone? 'task-done': ''; return(
  • ) } }

      TodoMain.js代码如下

    import React from 'react';
    import TodoItem from './TodoItem';
    export default  class TodoMain extends React.Component{
        constructor(props){
            super(props);
            this.state = {
    
            };
        }
        componentDidMount(){
    
        }
        render() {
             if(this.props.todos.length == 0){
                 return(
                     
    恭喜您,目前没有待办事项!
    ) }else{ return (
      { this.props.todos.map((todo, index) => { return }) }
    ) } } }

      {..this.props}将App中的方法,通过props传递给组件TodoIten中  

    五 TodoFooter

            TodoFooter代码如下

                  

    import React from 'react';
    export default class TodoFooter extends React.Component{
        constructor(props){
            super(props);
            this.state = {
    
            };
        }
        componentDidMount(){
    
        }
        handlerSelectAll =(e) =>{
    //全选事件,调用父组件的全选事件 this.props.changeTodoState(null, e.target.checked, true); } handlerDeleteDOne= () => {
    //清除已选任务操作,调用父组件的事件 this.props.clearDone(); } render(){ let count = this.props.todoCount; if(count > 0){ return(
    ) }else{ return (
    ) } } }

      六项目中用到的样式

       样式文件放在style/index.less文件中

           

    body {
      font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
      font-size: 14px;
      line-height: 1.42857143;
      color: #333;
      background-color: #fff;
    }
    #root{
      width: 1170px;
      padding-right: 15px;
      padding-left: 15px;
      margin-right: auto;
      margin-left: auto;
    }
    .todo-header{
      .form-horizontal .form-group {
        margin-right: -15px;
        margin-left: -15px;
      }
      .form-group {
        margin-bottom: 15px;
      }
      .form-horizontal .control-label {
        padding-top: 7px;
        margin-bottom: 0;
        text-align: right;
      }
      .col-md-2 {
        float: left;
        width: 16.66666667%;
      }
      .col-md-10{
        width: 83.33333333%;
      }
      .form-control {
        display: block;
        width: 100%;
        height: 34px;
        padding: 6px 12px;
        font-size: 14px;
        line-height: 1.42857143;
        color: #555;
        background-color: #fff;
        background-image: none;
        border: 1px solid #ccc;
        border-radius: 4px;
        -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
        box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
        -webkit-transition: border-color ease-in-out .15s,-webkit-box-shadow ease-in-out .15s;
        -o-transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s;
        transition: border-color ease-in-out .15s,box-shadow ease-in-out .15s;
      }
    }
    .todo-main{
      padding-left: 0;
      margin-bottom: 20px;
      .item{
        position: relative;
        display: block;
        padding: 10px 15px;
        margin-bottom: -1px;
        background-color: #fff;
        border: 1px solid #ddd;
        .pull-left{
          float: left!important;
        }
      }
      .list-group-item-success{
        color: #3c763d;
        background-color: #dff0d8;
      }
    }
    .todo-main:first-child{
      border-top-left-radius: 4px;
      border-top-right-radius: 4px;
    }
    .todo-footer{
      margin-bottom: 40px;
      .clearTask{
        display: inline-block;
        margin-left: 20px;
        .btn{
          color: #fff;
          background-color: #337ab7;
          border-color: #2e6da4;
        }
        .btn:hover {
          color: #fff;
          background-color: #286090;
          border-color: #204d74;
        }
      }
    }
    .todo-empty{
    }
    input[type=checkbox], input[type=radio] {
      margin: 4px 0 0;
      margin-top: 1px\9;
      line-height: normal;
    }
    input[type="checkbox"] {
      margin-right: 10px;
    }
    button.close {
      display: none;
      font-size: 12px;
      height: 18px;
      width: 18px;
    }
    button.close {
      -webkit-appearance: none;
      padding: 0;
      cursor: pointer;
      background: 0 0;
      border: 0;
    }
    .close {
      float: right;
      font-size: 21px;
      font-weight: 700;
      line-height: 1;
      color: #000;
      text-shadow: 0 1px 0 #fff;
      filter: alpha(opacity=20);
      opacity: .2;
    }
    .btn-group-xs>.btn, .btn-xs {
      padding: 1px 5px;
      font-size: 12px;
      line-height: 1.5;
      border-radius: 3px;
    }
    .btn {
      display: inline-block;
      padding: 6px 12px;
      margin-bottom: 0;
      font-size: 14px;
      font-weight: 400;
      line-height: 1.42857143;
      text-align: center;
      white-space: nowrap;
      vertical-align: middle;
      -ms-touch-action: manipulation;
      touch-action: manipulation;
      cursor: pointer;
      -webkit-user-select: none;
      -moz-user-select: none;
      -ms-user-select: none;
      user-select: none;
      background-image: none;
      border: 1px solid transparent;
      border-radius: 4px;
    }
    .todo-wrap{
      min-height: 20px;
      padding: 19px;
      margin-bottom: 20px;
      background-color: #f5f5f5;
      border: 1px solid #e3e3e3;
      border-radius: 4px;
      -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.05);
      box-shadow: inset 0 1px 1px rgba(0,0,0,.05);
      margin-left: 25%;
    }
    .todo-empty{
      text-align: center;
    }
    .text-center {
      text-align: center;
    }
    .h1, h1 {
      font-size: 36px;
    }
    

      

     

     


    推荐阅读
    • 本文介绍了如何使用Express App提供静态文件,同时提到了一些不需要使用的文件,如package.json和/.ssh/known_hosts,并解释了为什么app.get('*')无法捕获所有请求以及为什么app.use(express.static(__dirname))可能会提供不需要的文件。 ... [详细]
    • Spring源码解密之默认标签的解析方式分析
      本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
    • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
      本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
    • PHP图片截取方法及应用实例
      本文介绍了使用PHP动态切割JPEG图片的方法,并提供了应用实例,包括截取视频图、提取文章内容中的图片地址、裁切图片等问题。详细介绍了相关的PHP函数和参数的使用,以及图片切割的具体步骤。同时,还提供了一些注意事项和优化建议。通过本文的学习,读者可以掌握PHP图片截取的技巧,实现自己的需求。 ... [详细]
    • Webpack5内置处理图片资源的配置方法
      本文介绍了在Webpack5中处理图片资源的配置方法。在Webpack4中,我们需要使用file-loader和url-loader来处理图片资源,但是在Webpack5中,这两个Loader的功能已经被内置到Webpack中,我们只需要简单配置即可实现图片资源的处理。本文还介绍了一些常用的配置方法,如匹配不同类型的图片文件、设置输出路径等。通过本文的学习,读者可以快速掌握Webpack5处理图片资源的方法。 ... [详细]
    • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
    • 本文介绍了在Linux下安装Perl的步骤,并提供了一个简单的Perl程序示例。同时,还展示了运行该程序的结果。 ... [详细]
    • web.py开发web 第八章 Formalchemy 服务端验证方法
      本文介绍了在web.py开发中使用Formalchemy进行服务端表单数据验证的方法。以User表单为例,详细说明了对各字段的验证要求,包括必填、长度限制、唯一性等。同时介绍了如何自定义验证方法来实现验证唯一性和两个密码是否相等的功能。该文提供了相关代码示例。 ... [详细]
    • 本文介绍了在CentOS上安装Python2.7.2的详细步骤,包括下载、解压、编译和安装等操作。同时提供了一些注意事项,以及测试安装是否成功的方法。 ... [详细]
    • 网络请求模块选择——axios框架的基本使用和封装
      本文介绍了选择网络请求模块axios的原因,以及axios框架的基本使用和封装方法。包括发送并发请求的演示,全局配置的设置,创建axios实例的方法,拦截器的使用,以及如何封装和请求响应劫持等内容。 ... [详细]
    • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
      本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
    • 如何提高PHP编程技能及推荐高级教程
      本文介绍了如何提高PHP编程技能的方法,推荐了一些高级教程。学习任何一种编程语言都需要长期的坚持和不懈的努力,本文提醒读者要有足够的耐心和时间投入。通过实践操作学习,可以更好地理解和掌握PHP语言的特异性,特别是单引号和双引号的用法。同时,本文也指出了只走马观花看整体而不深入学习的学习方式无法真正掌握这门语言,建议读者要从整体来考虑局部,培养大局观。最后,本文提醒读者完成一个像模像样的网站需要付出更多的努力和实践。 ... [详细]
    • VueCLI多页分目录打包的步骤记录
      本文介绍了使用VueCLI进行多页分目录打包的步骤,包括页面目录结构、安装依赖、获取Vue CLI需要的多页对象等内容。同时还提供了自定义不同模块页面标题的方法。 ... [详细]
    • 本文介绍了Sencha Touch的学习使用心得,主要包括搭建项目框架的过程。作者强调了使用MVC模式的重要性,并提供了一个干净的引用示例。文章还介绍了Index.html页面的作用,以及如何通过链接样式表来改变全局风格。 ... [详细]
    • JavaScript和HTML之间的交互是经由过程事宜完成的。事宜:文档或浏览器窗口中发作的一些特定的交互霎时。能够运用侦听器(或处置惩罚递次来预订事宜),以便事宜发作时实行相应的 ... [详细]
    author-avatar
    橘子火4
    这个家伙很懒,什么也没留下!
    PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
    Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有