保姆级别手把手教写React的todolist案例


前言

TodoList是一个前端学习很不错的案例,不管是用原生javascript,还是vue,React来实现TodoList的功能,在前端学习中都是很重要的,这篇文章用React来实现简单的一个TodoList案例


一、React项目初始

1.创建react初始项目

a.打开一个文件夹,进入cmd
在这里插入图片描述
b.输入 命令行 create-react-app + 文件名 创建一个react项目
在这里插入图片描述
c.项目创建成功
在这里插入图片描述
4.用编辑器打开该文件, 或者直接cmd进入该文件目录
输入命令行 npm start 启动React项目

cmd直接进入
在这里插入图片描述
从项目文件进
在这里插入图片描述
至此一个React项目就创建完成了
在这里插入图片描述

2.项目初始化

删除项目文件中所有不需要的文件资源
同时将App.js,index.js, index.html这几个文件中的无效代码删除干净
在这里插入图片描述
这样就可以看到一个空白的页面环境

在这里插入图片描述

二、搭建项目

1.页面布局

App.js文件

a.初始化App组件,简单设计组件布局

import React, { Fragment } from "react";
import { Component } from "react";

class App extends Component {
    constructor(props) {
        super(props);
    }

    render() {
        return (
            <Fragment>
                <input></input>
                <button>提交</button>
            </Fragment>
        );
    }

   
}

export default App;

在这里插入图片描述
b.在 class 中,我们通过在构造函数中设置 this.state 并且初始化 { inputValue: ‘’, list: [] }

import React, { Fragment } from "react";
import { Component } from "react";

class App extends Component {
    constructor(props) {
        super(props);
        this.state = {
            inputValue: '121',
            list: []
        };

    }

    render() {
        return (
            <Fragment>
                <input ></input>
                <button>提交</button>
            </Fragment>
        );
    }
}

export default App;

c.对input进行数据绑定,修改inputvalue的数据,input框中数据改变
在这里插入图片描述

import React, { Fragment } from "react";
import { Component } from "react";

class App extends Component {
    constructor(props) {
        super(props);
        this.state = {
            inputValue: 'yyy',
            list: []
        };

    }

    render() {
        return (
            <Fragment>
                <input value={this.state.inputValue}></input>
                <button>提交</button>
            </Fragment>
        );
    }
}

export default App;

d.对input框绑定handlechange函数,看能否实现input框每次改变的时候值的获取。

import React, { Fragment } from "react";
import { Component } from "react";

class App extends Component {
    constructor(props) {
        super(props);
        this.state = {
            inputValue: 'yyy',
            list: []
        };

    }

    render() {
        return (
            <Fragment>
                <input value={this.state.inputValue} onChange={this.handleChange}></input>
                <button>提交</button>
            </Fragment>
        );
    }

    handleChange(e) {
        alert(e.target.value);
    }
}

export default App;

在这里插入图片描述

做到这儿我们也发现了,虽然弹窗弹出来了一个yy, 但是input框中依旧是yy,说明现在的input框中的值并不能由视图直接去改变,我们应该在handleChange函数中实现这样一个功能,可以通过改变input的value绑定的inputValue,来改变视图中input框中的值。

e.于是我们修改handleChange函数来实现这个功能

import React, { Fragment } from "react";
import { Component } from "react";

class App extends Component {
    constructor(props) {
        super(props);
        this.state = {
            inputValue: 'yyy',
            list: []
        };

    }

    render() {
        return (
            <Fragment>
                <input
                    value={this.state.inputValue}
                    onChange={this.handleChange}></input>
                <button>提交</button>
            </Fragment>
        );
    }

    handleChange(e) {
        //alert(e.target.value);
        this.setState(() => (
            {
                inputValue: e.target.value
            }
        ));
    }
}

export default App;

结果报错了
在这里插入图片描述

在React中,传递的事件参数不是一个字符串,而是一个实实在在的函数,代码中的handleChange()函数并不是我们主动调用的,而是触发onChange的事件时,react内部再去调用这个函数。而react的内部是不知道这里的this是指向哪里的,因此我们要自己通过bind改变事件方法的指向。

所以代码修改如下

import React, { Fragment } from "react";
import { Component } from "react";

class App extends Component {
    constructor(props) {
        super(props);
        this.state = {
            inputValue: 'yyy',
            list: []
        };
        // 为了在回调中使用 `this`,这个绑定是必不可少的
        this.handleChange = this.handleChange.bind(this)
    }

    render() {
        return (
            <Fragment>
                <input
                    value={this.state.inputValue}
                    onChange={this.handleChange}></input>
                <button>提交</button>
            </Fragment>
        );
    }

    handleChange(e) {
        //alert(e.target.value);
        this.setState(() => (
            {
                inputValue: e.target.value
            }
        ));
    }
}

export default App;

f.对state中list数据的渲染
在这里插入图片描述

import React, { Fragment } from "react";
import { Component } from "react";

class App extends Component {
    constructor(props) {
        super(props);
        this.state = {
            inputValue: 'yyy',
            list: ['学习React', '学习英语']
        };
        // 为了在回调中使用 `this`,这个绑定是必不可少的
        this.handleChange = this.handleChange.bind(this)
    }

    render() {
        return (
            <Fragment>
                <input
                    value={this.state.inputValue}
                    onChange={this.handleChange}></input>
                <button>提交</button>
                <ul>
                    {this.state.list.map((item, index) => {
                        return (<div key={index}>{item}</div>)
                    })}
                </ul>
            </Fragment>
        );
    }

    handleChange(e) {
        //alert(e.target.value);
        this.setState(() => (
            {
                inputValue: e.target.value
            }
        ));
    }
}

export default App;

g.实现点击提交按钮添加待办事件

import React, { Fragment } from "react";
import { Component } from "react";

class App extends Component {
    constructor(props) {
        super(props);
        this.state = {
            inputValue: 'yyy',
            list: ['学习React', '学习英语']
        };
        // 为了在回调中使用 `this`,这个绑定是必不可少的
        this.handleChange = this.handleChange.bind(this)
        this.handleAdd = this.handleAdd.bind(this)
    }

    render() {
        return (
            <Fragment>
                <input
                    value={this.state.inputValue}
                    onChange={this.handleChange}></input>
                <button onClick={this.handleAdd}>提交</button>
                <ul>
                    {this.state.list.map((item, index) => {
                        return (<div key={index}>{item}</div>)
                    })}
                </ul>
            </Fragment>
        );
    }

    handleChange(e) {
        //alert(e.target.value);
        this.setState(() => (
            {
                inputValue: e.target.value
            }
        ));
    }

    handleAdd() {
   		//preState是setState方法自带的参数,表示未修改前的State
        this.setState((preState) => (
            {
                inputValue: '',
                //...preState.list,是对未修改前的list进行展开
                list: [...preState.list, preState.inputValue]
            }
        ))
    }
}

export default App;

h.点击待办事件实现删除功能

import React, { Fragment } from "react";
import { Component } from "react";

class App extends Component {
    constructor(props) {
        super(props);
        this.state = {
            inputValue: 'yyy',
            list: ['学习React', '学习英语']
        };
        // 为了在回调中使用 `this`,这个绑定是必不可少的
        this.handleChange = this.handleChange.bind(this);
        this.handleAdd = this.handleAdd.bind(this);
        this.handleDelete = this.handleDelete.bind(this);
    }

    render() {
        return (
            <Fragment>
                <input
                    value={this.state.inputValue}
                    onChange={this.handleChange}></input>
                <button onClick={this.handleAdd}>提交</button>
                <ul>
                    {this.state.list.map((item, index) => {
                        return (
                            <li
                                key={index}
                                onClick={this.handleDelete}>
                                {item}
                            </li>)
                    })}
                </ul>
            </Fragment>
        );
    }

    handleChange(e) {
        //alert(e.target.value);
        this.setState(() => (
            {
                inputValue: e.target.value
            }
        ));
    }

    handleAdd() {
        this.setState((preState) => (
            {
                inputValue: '',
                list: [...preState.list, preState.inputValue]
            }
        ))
    }

    handleDelete(index) {
        this.setState((preState) => {
            //immutable
            //state不允许我们做任何改变
            const list = [...preState.list];
            list.splice(index, 1);
            return {
                list
            }
        })
    }
}

export default App;

三、组件拆分

1.分析

通过分析,我们将下面的list单独拿出来放在一个组件Item中,所以我们新建一个Item.js文件,并将其引入到App.js文件中使用,其中我们涉及到了组件之间值的传递,和vue一样,父组件向子组件传值 也是通过 props 来传,在子组件中用 this.props.xx 接收父组件传来的值。
在这里插入图片描述

2.全部代码

index.js文件

import React, { Fragment } from "react";
import { Component } from "react";
import Item from "./Item";

class App extends Component {
    constructor(props) {
        super(props);
        this.state = {
            inputValue: 'yyy',
            list: ['学习React', '学习英语']
        };
        // 为了在回调中使用 `this`,这个绑定是必不可少的
        this.handleChange = this.handleChange.bind(this);
        this.handleAdd = this.handleAdd.bind(this);
        this.handleDelete = this.handleDelete.bind(this);
    }

    render() {
        return (
            <Fragment>
                <input
                    value={this.state.inputValue}
                    onChange={this.handleChange}></input>
                <button onClick={this.handleAdd}>提交</button>
                <ul>
                    {this.getList()}
                </ul>
            </Fragment>
        );
    }

    getList() {
        return (
            this.state.list.map((item, index) => {
                return (
                    <div index={index}>
                        <Item item={item}
                            handleDelete={this.handleDelete}
                            key={index} />
                    </div>
                )
            })

        )
    }
    handleChange(e) {
        //alert(e.target.value);
        this.setState(() => (
            {
                inputValue: e.target.value
            }
        ));
    }

    handleAdd() {
        this.setState((preState) => (
            {
                inputValue: '',
                list: [...preState.list, preState.inputValue]
            }
        ))
    }

    handleDelete(index) {
        this.setState((preState) => {
            //immutable
            //state不允许我们做任何改变
            const list = [...preState.list];
            list.splice(index, 1);
            return {
                list
            }
        })
    }
}

export default App;

item.js文件

import React, { Component, Fragment } from "react";

class Item extends Component {
    constructor(props) {
        super(props);
        this.state = {};
        this.handleClick = this.handleClick.bind(this);
    }

    render() {
        return (
            <Fragment>
                <div onClick={this.handleClick}>{this.props.item}</div>
            </Fragment>
        )
    }

    handleClick() {
        const { index, handleDelete } = this.props;
        handleDelete(index);
    }
}

export default Item

四、总结

学习了几天的React了,因为一些事,导致最近几天的进度放慢了。因为先学的Vue,觉得很多操作和vue的操作挺像的。但React的学习,让我慢慢喜欢上了看英文的文档,还有论坛。通过这个todolist案例,我对react的基础语法更熟练,对常见的问题也有了处理经验。希望通过这篇文章,大家可以了解React的基础操作,也欢迎大佬对我的代码提出修改意见,希望后面依旧可以坚持一周一篇博客,对已经学习的知识有个及时的输出,后面还会对之前学的JS基础,ES6的学习写些总结。

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值