用react写todolist

2019-09-15 01:27:11 qq_17025903 阅读数 210

一、TodoList实现列表添加删除功能

添加webpack命令: yarn add webpack

创建components 目录及TodoList.js

pages 目录创建 show用来渲染TodoList组件

TodoList.js 代码

import React,{ Component } from 'react';
//Fragment 隐藏外层标签
class TodoList extends Component{
  //调用父类Component的构造函数,固定写法。
  constructor(props){
    super(props);
    //创建数据
    this.state={
      inputValue:'hello',
      list:['学习React','学习前端']
    }
  }
  render() {
    return (
      <div>
        {/*jsx语法,有提示。bind 改变this指向为调用的函数 */}
        <input onChange={this.handleInputChange.bind(this)} value={this.state.inputValue}/>
        <button onClick={this.handleBtnClick.bind(this)}>提交</button>
        <ul>
          {
            // 循环输出list
            this.state.list.map((item,index)=>{
              return (
                <li onClick={this.handleItemDelete.bind(this,index)} key={index}>
                  {item}
                </li>
              )
            })
          }
        </ul>
      </div>

    )
  }

  handleInputChange(e){
    this.setState({
      inputValue:e.target.value
    })
  }
  //添加
  handleBtnClick(){
    this.setState({
      //展开运算符,拿到以前数组的内容,生成新的数组。
      list:[...this.state.list,this.state.inputValue],
      inputValue:''
    })
  }
  //删除 index为下标
  handleItemDelete(index){
    const list=[...this.state.list];
    //删除一个下标为index的值
    list.splice(index,1);
    this.setState({
      list:list
    })
  }
}
export default  TodoList;

show.js 代码

import React from 'react';
import TodoList from '../components/TodoList';




export default function() {

  return (
    <div>
    <TodoList></TodoList>
    </div>
  );
}

测试

点击按钮可以增加,点击文字可以删除。

二、拆分组件修改功能

创建 TodoItem.js 通过this.props.content获取父组件传递的内容

import React,{ Component } from 'react';

class TodoItem extends Component{
constructor(props){
  super(props);
  this.handleClick=this.handleClick.bind(this);
}
  render() {
    return (
      <div onClick={this.handleClick}>
        {this.props.content}
      </div>

    )
  }
  handleClick(){
    this.props.deleteItem(this.props.index)
  }
}
export default  TodoItem;

TodoList.js 引入子组件

import React,{ Component } from 'react';
import TodoItem from "@/components/TodoItem";
//Fragment 隐藏外层标签
class TodoList extends Component{
  //调用父类Component的构造函数,固定写法。
  constructor(props){
    super(props);
    //创建数据
    this.state={
      inputValue:'hello',
      list:['学习React','学习前端']
    }
  }
  render() {
    return (
      <div>
        {/*jsx语法,有提示。bind 改变this指向为调用的函数 */}
        <input onChange={this.handleInputChange.bind(this)} value={this.state.inputValue}/>
        <button onClick={this.handleBtnClick.bind(this)}>提交</button>
        <ul>
          {
            // 循环输出list
            this.state.list.map((item,index)=>{
              return (
                <div>
                  {/*组件内容传递*/}
                    <TodoItem content={item} index={index} deleteItem={this.handleItemDelete.bind(this)}/>
                  {/*<li onClick={this.handleItemDelete.bind(this,index)} key={index}>*/}
                  {/*{item}*/}
                  {/*</li>*/}
                </div>

              )
            })
          }
        </ul>
      </div>

    )
  }

  handleInputChange(e){
    this.setState({
      inputValue:e.target.value
    })
  }
  //添加
  handleBtnClick(){
    this.setState({
      //展开运算符,拿到以前数组的内容,生成新的数组。
      list:[...this.state.list,this.state.inputValue],
      inputValue:''
    })
  }
  //删除 index为下标
  handleItemDelete(index){
    const list=[...this.state.list];
    //删除一个下标为index的值
    list.splice(index,1);
    this.setState({
      list:list
    })
  }
}
export default  TodoList;

 

2018-09-06 15:19:31 BeautyBeier 阅读数 206

React现在很流行的前端开发框架,这次以TodoList 开发来介绍react

一、开发前的准备

1.开发前电脑要安装好NodeJS(nodeJs 官网地址):`https://nodejs.org`
2.npm命令行安装; 安装成功后通过`node-v` 和 `npm-v`来查看是否安装成功; 
3.上面两个安装好后,运行命令行 `npm install -g create-react-app` ——安装react脚手架

二、使用react编写TodoList功能

这里写图片描述

上面就是todoList的效果组件效果图;
首先使用代码npm run start 来启动项目,它的入口文件在下图文件src目录的index.js;
这里写图片描述

新建一个todoList的js文件;
在index.js中引入import TodoList from './TodoList';

三、jsx语法


import React, {
    Component,
    Fragment
} from 'react'
class TodoList extends Component {
    constructor(props) {
        super(props);
        this.state = {
            inputValue: 'this is input',
            list: []
        }
    }
    render() {
        return ( 
            < div > 
                < div > 
                    < input  
                    value = {this.state.inputValue}
                    onChange = {this.handleInputChange.bind(this)}
                    / > 
                    < button > 提交 < /button> 
                 < /div > 
                 < ul > 
                 < li > learn react < /li>
                  < li > it is amazing < /li > 
                  < /ul>
            < /div > )
    }

    handleInputChange(e) {
        this.setState({
            inputValue:e.target.value  //通过setState来改变input中的值
        })
    }
}
export default TodoList

react中通过this.state来定义数据,react是单向数据绑定,在改变数据的时候,使用this.State 来改变数据。

2019-01-10 15:54:50 wanglei_samrtfish 阅读数 274

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="react4.aspx.cs" Inherits="react4" %>


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.3/react.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.3/JSXTransformer.js"></script>
    <style>
        *{
            padding: 0;
            margin: 0;
        }
        ul{
            list-style: none;
        }
        .container{
            margin-left: 200px;
            margin-top: 100px;
        }
        button{
            width: 100px;
            height: 20px;
            margin-left: 10px;
        }
        input{
            margin-top: 10px;
        }
    </style>
</head>
<body>
     <p>返回文章: <a href="https://www.cnblogs.com/6long/p/6044503.html">react的TodoList增删改)</a></p>
    <div id="container" class="container"></div>


    <script type="text/jsx">

        // TodoList 组件是一个整体的组件,最终的React渲染也将只渲染这一个组件
        // 该组件用于将『新增』和『列表』两个组件集成起来,并且存储 arr 的数据
        var TodoList = React.createClass({
            // 初始化数据
            getInitialState: function () {
                return {
                    //数组存储
                    arr: [{
                        title:"早餐",
                        content:"牛奶",
                        time:"10"
                    },
                        {
                            title:"午餐",
                            content:"肉奶",
                            time:"13"
                        },
          
                        {
                            title:"晚餐",
                            content:"水饺",
                            time:"20"
                        }
        
        ]
                };
            },
            // 接收一个传入的数据,并将它实时更新到组件的 state 中,以便组件根据数据重新render
            // 只要改变了 state ,react自动执行 reader 计算

            //任务标题、内容、时间,三部分需要用到数组中的对象
            handleChange: function (rows) {
         
                this.setState({
    //                arr: new Mask(title,content,time)
                    arr:rows
                });
    //            console.log(arr)
            },
            render: function () {
                return (
                        <div>
                            {/*
                             AddList 组件,传入两个属性onAdd,todo
                             todo将 todolist 的数据传入到组件,当新增时,更新todolist数据
                             onAdd -  将 handleChange 函数传入到组件,新增时,用它来处理最新的todolist数据
                             */}
                            <AddList onAdd={this.handleChange} todo={this.state.arr} />
                            {/*
                             集成 DeleteList 组件,传入两个属性 onDel,todo
                             todo将 todolist 的数据传入到组件,当删除时,更新todolist数据
                             onDel - 将 handleChange 函数传入到组件,删除时,用它来处理最新的todolist数据
                             */}
                            <DeleteList onDel={this.handleChange} todo={this.state.arr} />
                        </div>
                );
            }
        });
        /*
        * ddList 组件用于新增数据,需要todo 和 onAdd 两个属性
        * 当从 input 中获取数据时,将新数据 push 到todo中,
        * 然后使用 onAdd 调用 TodoList 的 handleChange 来更新state,然后react自动render
        * */


    //    增加和查询可以合并到一起用
        var AddList = React.createClass({
    //        增加数据模块
            handleAdd: function (e) {
                e.preventDefault();
                // 通过 refs 获取相信input元素,然后获取输入的内容
                var titleDOM = this.refs.title.getDOMNode();
                var titleValue = titleDOM.value.trim();
                var contentDOM = this.refs.content.getDOMNode();
                var contentValue = contentDOM.value.trim();
                var timeDOM = this.refs.time.getDOMNode();
    //            时间强行转化位数字,方便后续排序
                var timeValue = Number(timeDOM.value.trim());

     

                // 获取传入的todolist数据
                var rows = this.props.todo || [];
    //            console.log("ok")
                    if (titleValue !== '' && contentValue !== '' && timeValue !== '') {
                        // 更新数据,并使用 onAdd 更新到 TodoList 组件的 state 中
                        if(!isNaN(timeValue)){
    //                        把对应的每个input的值通过对象保存到数组中
                            rows.push(
                                    {
                                        title:titleValue,
                                        content:contentValue,
                                        time:timeValue
                                    }
                            );
                            this.props.onAdd(rows);
                        }else{
                            alert("日期只能为数字(单位:天),请重新输入!");
                        }

                    }else{
                        alert("您有信息未填写,请核对后再【添加】");
                    }
    //            把值保存到数组后,及时清空input,用户体验好
                titleDOM.value = contentDOM.value = timeDOM.value= '';
            },

            /*              搜索数据模块
            * 点击搜索的时候,先把所有className的input的display设置为none隐藏
            * 数组中遍历的时候,把符合条件的,设为 显示        *
            * */
            handleSearch:function(e) {
                e.preventDefault();

               <%-- console.log(this.refs.title.getDOMNode())--%>
                this.props.todo.map(function (item, i) {
                            if(item.time == 10){
                                 alert("10")
                             };
                  <%--  console.log(item.time + "......"+ i);--%>
                })
            },
            render: function () {
                return (
                    // 用回车键 和 点击事件,触发 handleAdd 事件,用户体验好

                        <form onsubmit={this.handleAdd}>
                            <input type="text" ref="title" id="title" placeholder="请输入任务标题" autoComplete="off" />
                            <input type="text" ref="content" id="content" placeholder="请输入内容" autoComplete="off" />
                            <input type="text" ref="time" id="time" placeholder="请输入到期时间(单位:天)" autoComplete="off" />
                            <button className="add" onClick={this.handleAdd} >添加</button>
                            <button className="search" onClick={this.handleSearch}>搜索/排序</button>
                        </form>
                );
            }
        });

        /*      DeleteList 完成删除 修改功能
        *可以删除某一项内容,有 noDel,todo两个属性
        *遍历todo的内容,生成数据列表和删除按钮
        *对某一项执行删除时,将todo中的数据删除
        * 然后通过 onDel 事件调用 TodoList 的 handleChange 来更新state,然后react自动render
        *修改值时用的中间变量
        */
        var titleV,contentV,timeV;
        var DeleteList = React.createClass({

            //删除事件绑定
            handleDel: function (e) {
                var delIndex = e.target.getAttribute('data-key');
              

                // 更新数据,并使用 onDel 更新到 TodoList 的 state 中,以便 React自动render
                this.props.todo.splice(delIndex, 1);
                this.props.onDel(this.props.todo);
            },
    //        修改事件绑定
            titleChange: function (e) {
    //            console.log(e.target.value)
                titleV = e.target.value;
    //            console.log(titleV)
            },
            contentChange: function (e) {
                contentV = e.target.value;
            },
            timeChange: function (e) {
                timeV = e.target.value;
            },
            /*
            * 修改的时候,用户先直接修改数据
            * 然后点击确认修改的时候在完成对数组值的修改操作
            * */
            handleAlt: function (e) {
                e.preventDefault();
                var delIndex = e.target.getAttribute('data-key');
                this.props.todo[delIndex].title = titleV;
                this.props.todo[delIndex].content = contentV;
                this.props.todo[delIndex].time = timeV;
                console.log(this.props.todo)

            },
            render: function () {
    //            console.log(this.props.todo.map)
                return (
                        <ul id="todo-list">
                            {
                                // {/* 遍历数据 */}
                                this.props.todo && this.props.todo.map(function (item, i) {
                                    return (
                                            <li ref="tip">
                                                <input defaultValue={item.title} onChange={this.titleChange} className="val"/>
                                                <input defaultValue={item.content}  onChange={this.contentChange} className="val"/>
                                                <input defaultValue={item.time}  onChange={this.timeChange} className="val"/>
                                                <button className="destroy" onClick={this.handleDel} data-key={i}>delete</button>
                                                <button className="alter" onClick={this.handleAlt} data-key={i}>Alt</button>
                                            </li>
                                    );
                                }.bind(this)) // {/* 绑定函数的执行this - 以便 this.handleDel */}
                            }
                        </ul>
                );
            }
        });

        React.render(<TodoList />, document.getElementById('container'));

    </script>
</body>
</html>

效果截图

 

2019-03-15 13:15:52 csdn_zsdf 阅读数 2095

在这里插入图片描述
一个todolist基本的功能点包括:

  1. 点击复选框标记完成或者未完成,且相应的文字出现删除线
  2. 从列表中移除item
  3. 添加item

首先它是由todolist title 、todolist、和addtodo三部分组成。由于todolist title 和addtodo比较简单,在这里只将todolist拆分成组件。
创建一个ListItem组件。含有一个render方法

class ListItem extends Component {
  render() {
    return (
      <ul>
        {
          this.props.data.map(element => {
            return (
              <li className="listItem" key={element.name}>
                <input type="checkbox"/>
                <span>{element.name}</span>
                <button className="delete">删除</button>
              </li>
             )
        })
      }
    </ul>
   )
  }
 }
 export default ListItem

this.props.data是父组件传下来的一个list。遍历该list的每一项渲染出来。(注:上面代码体现了 JSX 的基本语法规则:遇到 HTML 标签(以 < 开头),就用 HTML 规则解析;遇到代码块(以 { 开头),就用 JavaScript 规则解析。)
此时一个todo的list组件就封装好了,export default出去,让需要的去组件使用。

在父组件TodoList中使用该ListItem组件。

import ListItem from './ListItem'
class TodoList extends Component {
  render() {
    return (
      <div className="reactTodoList">
      	<header className="header">React todo list</header>
      	<ListItem data={this.state.list} />
      	<footer>
        	<input type="text"  placeholder="添加todo"></input>
        	<button className="addTodo" >添加</button>
      	</footer>
   	 </div>
    )
  }
}
ReactDOM.render( <TodoList />,  document.getElementById('root'))

由上基本的框架已经搭建出来了,接下来就是list中需要填充数据。
在ListItem组件中有一个接受到的this.props.data的数组,其来自于父组件上的<ListItem data={this.state.list} />。父组件中的state需要声明一下:

constructor() {
    super()
    this.state = {
      list: [{
        name: 'learn english', status: 0
      },{
        name: 'Learn guitar', status: 0
      }, {
        name: 'weight less than 100', status: 0
      }, {
        name: 'have 100,000 deposit', status: 0
      }]
    }
  }

在render函数上插入这一段代码,添加一个类构造函数来初始化状态 this.state。React 里,只需更新组件的 state,然后根据新的 state 重新渲染用户界面(不要操作 DOM)。
接下来父组件通过<ListItem data={this.state.list} />将其list传入到了子组件,子组件中使用map进行渲染。至此页面渲染结束。

1. complete todo
现在要添加交互了。首先实现勾选checkbox出现✅,并且对应的文字出现删除线。注意父组件传入的data的数组中status表示该todo是否完成,所以status就是一个重要的信息。0表示未完成,点击checkbox后,status变为1,表示完成,且文字出现删除线。

<li className="listItem" key={element.name}>
    <input type="checkbox"
       checked={element.status === 1}
       onChange={this.completeTask.bind(this, element.name)}/>
    <span style={{textDecorationLine: element.status === 0 ? 'none' : 'line-through'}}>{element.name}</span>
    <button className="delete">删除</button>
 </li>

这段代码来自于ListItem的组件(可以向上找),现在我们添加在input元素上一个checked属性,和一个onChange事件。
checked表示当status为1时表示完成,当checkbox发生变化的时候就要去更新父组件中的this.status.list相应的status。所以需要一个触发事件completeTask。将此item的name传给父组件,父组件根据name查找到相应的listItem,更新其status。(子组件需要向父组件传值使用函数)。此时在该子组件中定义一个completeTask函数(在render函数上方)。

completeTask(name) {
    this.props.completeTask(name)
 }

学过vue的应该知道,这有点像vue的子组件emit事件到父组件,父组件通过该事件来进行局部处理。

 <span style={{textDecorationLine: element.status === 0 ? 'none' : 'line-through'}}>{element.name}</span>

在上面这段代码中,通过判断: element.status来添加style,是否出现删除线。

在父组件中应该这样:

<ListItem data={this.state.list} completeTask={this.completeTask1.bind(this)}/>

此段代码来自于父组件TodoList中(向上查找)。代码中的completeTask函数来自于子组件中,completeTask1是需要在父组件中进行处理的父组件函数。这个completeTask1需要完成的事情就是根据子组件传上来的name值,在this.state.list中找到之后更新它的status。若为1更新为0,反之亦然。

completeTask1(name) {
    const TodoList = []
    this.state.list.forEach((element, index) => {
      if (element.name === name) {
        const item = this.state.list[index]
        TodoList.push(Object.assign({}, item, {status: item.status === 0 ? 1 : 0}))
        this.setState({
          list: TodoList
        })
      } else {
        TodoList.push(element)
      }
    })
  }

父组件中中的completeTask1函数,遍历this.state.list根据name查找到对应的item,通过Object.assign({}, item, {status: item.status === 0 ? 1 : 0}))来更改status。注:state中的所有数据不允许直接更改。

this.setState({
    list: TodoList
 })

用来更新state中的数据。

至此就实现了点击checkbox复选框出现对号并且相应文字出现删除线。(完成item的功能)

2. delete todo
点击子组件ListItem中的delete按钮,同样通过函数向父组件传递一个name,父组件根据这个name从this.state.list中移除该item。
子组件中

   <button className="delete" onClick={this.deleteTask.bind(this, element.name)}>删除</button>

render函数上方

deleteTask(name) {
    this.props.deleteItem(name)
}

父组件中

<ListItem data={this.state.list} deleteItem={this.deleteItem1.bind(this)}
        completeTask={this.completeTask.bind(this)}/>

多了一个deleteItem的函数。
deleteItem1函数中通过name查找item,删除

deleteItem1(name) {
    const data = this.state.list.filter(element => element.name !== name)
    this.setState({
      list: data
    })
  }

此时一个删除todolist的功能也已经完成。接下来就是添加todo了。

3. add todo
添加todo只需要在父组件中进行操作。
首先需要获得文本框中的输入内容,接下来通过点击添加按钮来给this.state.list中push一项就可以实现啦。

<footer>
        <input type="text" value={this.state.inputVal} onChange={this.handleChange.bind(this)} placeholder="添加todo"></input>
        <button className="addTodo" onClick={this.addTask.bind(this)}>添加</button>
  </footer>

该部分就是添加todo的部分啦。首先input绑定了this.state.inputVal, 并且当输入内容变化的时候更新state中的inputVal。
首先

constructor() {
    super()
    this.state = {
      list: [{
        name: 'learn english', status: 0
      },{
        name: 'Learn guitar', status: 0
      }, {
        name: 'weight less than 100', status: 0
      }, {
        name: 'have 100,000 deposit', status: 0
      }],
      inputVal: ''
    }
  }

注意添加了一个inputval,用来存储输入框中的内容。实现handleChange函数,并更新state.inputVal

handleChange(e) {
    this.setState({
      inputVal: e.target.value
    })
  }

实现了输入框的功能,接下来点击addTask的按钮需要实现添加todo的功能。并且添加成功后输入框中的内容为空。即inputVal为空字符串。

addTask() {
    if (!this.state.inputVal) return
    this.setState({
      list: [...this.state.list, {
        name: this.state.inputVal,
        status: 0
      }],
      inputVal: ''
    })
  }

这个函数中若输入为空不执行任何操作(你也可以添加提示)。添加成功后更新list和inpuVal。
至此一个简单的todolist功能就完成啦。

完整代码见: https://github.com/zhangsundf/React-todoList

2019-05-25 14:40:49 Honey_tianming 阅读数 252
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="./build/react-0.14.0.js"></script>
    <script src="./build/react-dom.js"></script>
    <script src="./build/browser.min.js"></script>
</head>
<body>
  <div id="app"></div>
  <script type="text/babel">
    class Todolist extends React.Component{
       constructor(props){
         super(props)
         this.state={
            todolists:[    
            {text:'早上九点上班'},
            {text:'下午两点上班'},
            {text:'晚上七点下班'} 
            ]
         }
         this.addTodo=this.addTodo.bind(this)
         this.deleteTodo=this.deleteTodo.bind(this)  
       }

       addTodo(e){
        if(e.keyCode==13){
          console.log(e.target.value)
          if(e.target.value!=''){
            var todo = {text:e.target.value}
            this.state.todolists.push(todo)
            this.setState({
              todolists:this.state.todolists  
            })
            e.target.value='' 
          }
        }  
      }

      deleteTodo(e){
       var index= e.target.className
       console.log(index)
       this.state.todolists.splice(index,1)
       this.setState({
         todolists:this.state.todolists  
       })
       e.target.className=''
      }


       render(){
         return(
            <div>
            <input type="text" placeholder="请输入您的计划"  onKeyUp={this.addTodo} />
            <ol>
               {
                this.state.todolists.map((item,index)=>{
                  return (<li key={index}>{item.text}<span style={{color:'red',marginLeft:'15px'}} className={index} onClick={this.deleteTodo}>删除</span></li>)
                })               
              }
            </ol>
            </div>
         )
       }
    }
    var app = document.getElementById('app')
    ReactDOM.render(
      <Todolist/>,
      app        
    )
  </script>   
</body>
</html>      

效果如图
在这里插入图片描述

react-todolist2

阅读数 88