zoukankan      html  css  js  c++  java
  • React入门实战实例——ToDoList实现

    摘要:

     最近学习了一小段时间的React,对一些React开发组件的基础有了一点认识,跟着教学视频,自己实现了一个ToDoList组件的功能,今天把做这个组件的过程记录一下,加深学习印象,给同样的前端入门者做一个参考。

     一、实例展示和功能介绍

    1.1 实例展示

     视频1.1

     1.2 功能介绍

    •  添加待办事项,按enter键确定,同时清空输入框;
    • 通过checkbox是否勾选可以切换待办和已办事项;
    • 点击删除可以删除事项

    二、准备工作

    2.1 环境配置提醒

    准备之前:本文假定开发环境已配置完成,包括:

    • Node.js已安装;
    • cnpm 已安装; npm install -g cnpm --registry=https://registry.npm.taobao.org 
    • 脚手架工具已安装; npm install -g create-react-app / cnpm install -g create-react-app 

     注意:初次配置脚手架会出现禁止运行脚本的错误,解决办法点击:https://www.cnblogs.com/yaotuo/p/12240019.html

    2.2 新建React项目

    1.新建一个项目文件夹Code,使用VSCode,将Code文件加添加到工作区;

     图2.1

    2.右击Code文件夹,在选项卡中选择在终端中打开;

     

     图2.2

     3.在终端中输入如下命令,新建React项目: create-react-app todo-list 

     

     图2.3

    4.生成Rreact项目如下 :

     图2.4

    React开发主要是对src里的文件动手脚,node_modules主要防止各种依赖包,public放置一些公共文件,package.json这些是一些配置文件,在此不详述。

    2.3 文件分类

    • 在src目录下新建components文件夹,用来放置自己创建的组件;
    • 在src目录下新建assets文件加用来防止css文件和图片文件等静态资源;

    如图2.5所示:

     图2.5

    三、实现过程

     3.1 创建组件ToDoList

    components文件夹下新建ToDoList.jsx文件,编写如下代码,搭好一个组件的基本框架;代码如下:

    //导入React相关依赖
    import React from 'react';
    
    //创建一个组件
    class ToDoList extends React.Component{
        //构造函数
        constructor(props){
            super(props);
            //this是父组件(类)的一个实例,实例就类似于java里的一个类,创建了这个类型的一个对象,这个对象就是实例
            this.state = {
                //this.state里可以写一些初始化的数据
            }
        }
    
    
        //render渲染虚拟DOM
        render(){
    
            return(
                <div>
                    ToDoList
                </div>
            );
        }
    
    }
    
    
    //输出组件,使得该组件可以被其他组件调用
    export default ToDoList;

    组件中每个部分的功能,在注释里有简略描述。一个基本的组件一般包括以上的几个部分:

    • import导入的依赖;
    • 组件(class XXX extends React,Component);
    • 构造函数constructor;
    • render函数;
    • export输出组件;

    3.2 功能实现与解析

    1.初始化数据

    使用一个数组来保存数据,数组中每个元素为一个对象,该对象包括两个字段:title和checked,tile为字符串类型,checked为布尔类型,用来区分待办(false)已办(true);

     list:[
                    {
                        title:'吃饭',
                        checked:true
                    },
                    {
                        title:'跑步',
                        checked:false
                    },
                    {
                        title:'上班',
                        checked:false
                    },
                    {
                        title:'睡觉',
                        checked:true
                    },
           ]

    该数组在this.state中初始化:

     constructor(props){
            super(props);
            //this是父组件(类)的一个实例,实例就类似于java里的一个类,创建了这个类型的一个对象,这个对象就是实例
            this.state = {
                //this.state里可以写一些初始化的数据
                list:[
                    {
                        title:'吃饭',
                        checked:true
                    },
                    {
                        title:'跑步',
                        checked:false
                    },
                    {
                        title:'上班',
                        checked:false
                    },
                    {
                        title:'睡觉',
                        checked:true
                    },
                ],
            }
        }

    2.编写页面布局

    页面分为顶部的输入框(input)和下面的 待办事项列表 已办事项列表;在render中的return中编写(jsx);

        render(){
    
            return(
                <div>
                     <header>TodoList:  <input type = "text"/> </header>
    
                    <h2>待办事项</h2>
    
                    <hr />
                    
                    <ul>
                        {/* 多个li,后面会循环输出 */}
                        <li>
                            <input type="checkbox" /> -- <button>删除</button>
                        </li>
                    </ul>           
    
    
    
                    <h2>已完成事项</h2>
    
                    <hr />
                    <ul>
                        {/* 多个li,后面会循环输出 */}
                        <li>
                            <input type="checkbox"  /> -- <button>删除</button>
                        </li>
                    </ul>    
                </div>
            );
        }

     3.挂载到根节点下

    在index.js下,引入ToDoList组件

    import ToDoList from './components/ToDoList';

    然后挂在组件ToDoList

    import React from 'react';
    import ReactDOM from 'react-dom';
    import './index.css';
    import App from './App';
    import * as serviceWorker from './serviceWorker';
    import ToDoList from './components/ToDoList';
    
    ReactDOM.render(
      <React.StrictMode>
        {/* 此处是ToDoList组件 */}
        <ToDoList />   
      </React.StrictMode>,
      document.getElementById('root')
    );
    
    // If you want your app to work offline and load faster, you can change
    // unregister() to register() below. Note this comes with some pitfalls.
    // Learn more about service workers: https://bit.ly/CRA-PWA
    serviceWorker.unregister();

    简陋渲染效果如下:

     图3.1

    3.功能实现

    • 添加待办事项

    (1)使用ref属性,获取input输入值:

      在input标签上设置属性ref="inputToDo",然后在方法中可以通过 this.refs.inputToDo.value获取输入值;

    (2)添加键盘事件,监听输入变化,当输入enter时,添加待办事项;

      使用onKeyUp(键盘弹起)/onKeyDown(键盘按下)事件来监听键盘变化。当键盘变化后,触发添加函数,将输入值添加到待办事项中;代码如下:

    jsx:

    <header>TodoList:  <input type = "text" ref = "inputToDo" onKeyUp = {this.addToDo}/> </header>

    addToDo函数:

        addToDo = (event) => {
            console.log(event.keyCode);
            if(event.keyCode === 13)
            {
                let tempList = this.state.list;
                tempList.push({
                    title:this.refs.inputToDo.value,
                    checked:false,
                });
                this.setState({
                    list:tempList,
                });
                this.refs.inputToDo.value = '';
            }
        }

    (3)在constructor中使用bind绑定addToDo,这一步是必须的,否则方法不能执行,所有的方法都需要像这样绑定;

     this.addToDo = this.addToDo.bind(this);

     图3.2

    效果:

     

    视频3.1

    • 输出待办事项和已办事项

      使用map方法,循环遍历数组,输出每组数据;代码如下:

     <ul>
                        {/* 多个li,后面会循环输出 */}
                        {
                            this.state.list.map((value,index)=>{
                    {/*checked为false表示待办*/}
    if(!value.checked) { return ( <li>
                             {/* */} <input key = {index} type="checkbox" checked = {value.checked} onChange={this.checkboxChange.bind(this,index)}/> {value.title}-- <button>删除</button> </li> ); } }) } </ul>

    checked = {value.checked}表示复选框是否打勾,onChange事件触发一个改变事项状态的方法,index是数组的索引,该方法在下文实现;

      效果:

     图3.3

    • 待办和已办互相转换

      这一步的思路也很简单,其实就是在触发checkboxonChange事件时,将某一个事项的checked值变为相反的值(true->false/false->true),所以onChange后的方法需要传入数组的索引值,具体实现代码如下:

    jsx

    <input key = {index} type="checkbox" checked = {value.checked} onChange={this.checkboxChange.bind(this,index)}/> {value.title}-- <button>删除</button>
    checkboxChange
    checkboxChange = (index) => {
          let tempList = this.state.list;
          tempList[index].checked = !tempList[index].checked;
          this.setState({
              list:tempList,
         });
    }

     效果:

     视频3.2

    • 删除事项

     删除事项比较简单了,思路也是类似的,在button上添加onClick按钮,触发删除事件,传入参数index,然后根据index,使用数组的splice函数,删除某一待办事项。

    arrayA.splice(index,n)

    该方法第一个参数是数组中的元素位置,第二个参数是从index开始删除多少个元素。

    具体实现如下:

    jsx

      <li>
           <input key = {index} type="checkbox" checked = {value.checked} onChange={this.checkboxChange.bind(this,index)}/> {value.title}
           -- <button onClick={this.removeToDo.bind(this,index)}>删除</button>

    </li>

     removeToDo

        removeToDo = (index) => {
            let tempList = this.state.list;
            tempList.splice(index,1);
            this.setState({
                list:tempList,
            });
        }

    效果:即为开篇展示的效果 

    3.3 编写样式

     样式随便写了一下,不太好看,这里也把代码丢上来吧;

    index.css

    .list{
    
      padding: 10px;
    }
    
    .list li{
    
      line-height: 40px;
      margin-left: 30px;
    }
    
    .title{
    
      height: 44px;
    
      line-height: 44px;
    
      text-align: center;
    
      background: #000;
    
      color:#fff;
    }
    
    .title input{
    
      height: 40px;
    }
    
    
    .container{
      width: 800px;
      height: 1000px;
      margin-left: auto;
      margin-right: auto;
      background-color:  #D0D0D0;
      border: #fff solid 1px;
      border-radius: 5px;
    }
    
    .container h2{
      margin-left: 20px;
    }
    
    .del-btn {
      float: right;
      margin-right: 30px;
    }
    • 引入样式

      在ToDoList.jsx中按如下代码引入index.css

    import '../assets/index.css';

    3.4 整体效果

     

    视频3.3:整体效果展示

    四、整体代码

    • ToDoList.jsx
    //导入React相关依赖
    import React from 'react';
    import '../assets/index.css';
    
    //创建一个组件
    class ToDoList extends React.Component{
        //构造函数
        constructor(props){
            super(props);
            //this是父组件(类)的一个实例,实例就类似于java里的一个类,创建了这个类型的一个对象,这个对象就是实例
            this.state = {
                //this.state里可以写一些初始化的数据
                list:[
                    {
                        title:'吃饭',
                        checked:true
                    },
                    {
                        title:'跑步',
                        checked:false
                    },
                    {
                        title:'上班',
                        checked:false
                    },
                    {
                        title:'睡觉',
                        checked:true
                    },
                ],
            }
    
            this.addToDo = this.addToDo.bind(this);
            this.checkboxChange = this.checkboxChange.bind(this);
        }
    
        addToDo = (event) => {
            console.log(event.keyCode);
            if(event.keyCode === 13)
            {
                let tempList = this.state.list;
                tempList.push({
                    title:this.refs.inputToDo.value,
                    checked:false,
                });
                this.setState({
                    list:tempList,
                });
                this.refs.inputToDo.value = '';
            }
        }
    
    
        checkboxChange = (index) => {
            let tempList = this.state.list;
            tempList[index].checked = !tempList[index].checked;
            this.setState({
                list:tempList,
            });
        }
    
        removeToDo = (index) => {
            let tempList = this.state.list;
            tempList.splice(index,1);
            this.setState({
                list:tempList,
            });
        }
    
        //render渲染虚拟DOM
        render(){
    
            return(
                <div>
                     <header className = "title">TodoList:  <input type = "text" ref = "inputToDo" onKeyUp = {this.addToDo}/> </header>
                        <div className = "container">
                            <h2>待办事项</h2>
    
                            <hr />
    
                            <ul className = "list">
                                {/* 多个li,后面会循环输出 */}
                                {
                                    this.state.list.map((value,index)=>{
                                        if(!value.checked)
                                        {
                                            return (
                                                <li>
                                                    <input key = {index} type="checkbox" checked = {value.checked} onChange={this.checkboxChange.bind(this,index)}/> {value.title}
                                                    <button onClick={this.removeToDo.bind(this,index)} className = "del-btn">删除</button>
                                                </li>
                                            );
                                        }
    
                                    })
                                }
                            
                            </ul>           
                            <h2>已完成事项</h2>
    
                            <hr />
                            <ul className = "list">
                                {/* 多个li,后面会循环输出 */}
                                {
                                    this.state.list.map((value,index)=>{
                                        if(value.checked)
                                        {
                                            return (
                                                <li>
                                                    <input key = {index} type="checkbox" checked = {value.checked} onChange={this.checkboxChange.bind(this,index)}/> {value.title}
                                                    <button onClick={this.removeToDo.bind(this,index)} className = "del-btn">删除</button>
                                                </li>
                                            );
                                        }
                                    })
                                }
                            </ul>    
                     </div>               
                </div>
            );
        }
    
    }
    
    
    //输出组件,使得该组件可以被其他组件调用
    export default ToDoList;
    View Code
    • index.css 

    .red{
    
      color:red;
    }
    
    
    .list{
    
      padding: 10px;
    }
    
    .list li{
    
      line-height: 40px;
      margin-left: 30px;
    }
    
    .title{
    
      height: 44px;
    
      line-height: 44px;
    
      text-align: center;
    
      background: #000;
    
      color:#fff;
    }
    
    .title input{
    
      height: 40px;
    }
    
    
    .container{
      width: 800px;
      height: 1000px;
      margin-left: auto;
      margin-right: auto;
      background-color:  #D0D0D0;
      border: #fff solid 1px;
      border-radius: 5px;
    }
    
    .container h2{
      margin-left: 20px;
    }
    
    .del-btn {
      float: right;
      margin-right: 30px;
    }
    View Code
    • index.js 

    import React from 'react';
    import ReactDOM from 'react-dom';
    import './index.css';
    import App from './App';
    import * as serviceWorker from './serviceWorker';
    import ToDoList from './components/ToDoList';
    
    ReactDOM.render(
      <React.StrictMode>
        {/* <App /> */}
        <ToDoList />
      </React.StrictMode>,
      document.getElementById('root')
    );
    
    // If you want your app to work offline and load faster, you can change
    // unregister() to register() below. Note this comes with some pitfalls.
    // Learn more about service workers: https://bit.ly/CRA-PWA
    serviceWorker.unregister();
    View Code

    五、结语

    结语就算了吧,好困,睡了。 

    写博客费时间啊,大家要是看到有啥不对的地方,麻烦联系我修改哈,我水平太有限了,谢谢大佬们了。

  • 相关阅读:
    python库--pandas--文本文件读取
    python库--flashtext--大规模数据清洗利器
    PyCharm--帮助文档
    Git--命令
    symfony doctrine generate entity repository
    [转]MySQL性能优化的最佳20+条经验
    svn使用
    一致性hash
    JavaScript学习笔记 1
    curl发出请求
  • 原文地址:https://www.cnblogs.com/CherishTheYouth/p/CherishTheYouth_20200719_2.html
Copyright © 2011-2022 走看看