react入门之旅2——todoList案例之基础知识应用

案例

  1. 显示一个多选列表,每一个多选项后面有一个删除按钮,点击可删除
  2. 多选列表鼠标移入高亮显示并展示删除按钮,移除正常显示不展示删除按钮
  3. 列表上面有一个输入框,用户可以输入选项,回车添加进列表
  4. 列表底部有统计数据展示,展示【已完成X/全部Y】
  5. 底部右侧有一个清空勾选按钮,点击清除所有勾选

示意图:

项目思维

项目

        node_modules——依赖库

        public——公共文件目录(其中最重要的是首页的html)

        src——代码库

                componnents——组件库

                        Componnent_A——组件A

                                index.jsx——组件代码

                                index.css——组件样式代码

                        ...

                App.jsx——所有组件的父组件

                App.css——App组件样式

                index.js——渲染

这个目录层级,是工作中常用的层级关系,一般公司都采用这种,我们测试人员虽然不是做前端工作的,但还是需要和公司接轨

创建项目

webstorm-->File-->New-->Project...-->React,自定义一个项目名(本人创建的项目名:todo_demo),点击create

小坑:项目主目录下新建一个.env文件,添加【SKIP_PREFLIGHT_CHECK=true】

然后试运行,在控制台输入npm start,如下图所示

index

这个只是把App渲染到页面,这个是固定代码,基本不需要修改,所以先把这个写好

import React from "react";
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(<App/>, document.getElementById("root"));

拆分组件

App

        Header:头部输入框组件

        List:列表组件

                Item:列表元素组件

        Footer:底部数据展示&按钮组件

first:项目初始化

将每一个组件中的index中写好类式组件,快捷方式rcc,将类名更改为组件名

second:静态页面

这里需要使用到官网描述的一个知识点——状态提升,其实说到底,就是state只在父组件中维护,子组件只关心props

因为要写出静态页面,初始的数据需要先定义好

app

import './App.css';

import React, {Component} from 'react';
import Header from "./componnents/Header";
import List from "./componnents/List";
import Footer from "./componnents/Footer";

class App extends Component {

    state = {
        todos: [
            {id: "001", name: "练习", done: false},
            {id: "002", name: "react", done: true},
            {id: "003", name: "vue", done: false}
        ]
    }

    render() {

        const {todos} = this.state;

        return (
            <div>
                <Header/>
                <List todos={todos}/>
                <Footer/>
            </div>
        );
    }
}

export default App;

Header

import React, {Component} from 'react';
import './index.css'

class Header extends Component {
    render() {
        return (
            <input type="text" placeholder="请输入你的任务名称,按回车键确认"/>
        );
    }
}

export default Header;

Footer

import React, {Component} from 'react';
import './index.css'

class Footer extends Component {
    render() {
        return (
            <div>
                <input type="checkbox"/>
                <span>已完成{}</span>/全部{}
                <button>清除已完成任务</button>
            </div>
        );
    }
}

export default Footer;

List

import React, {Component} from 'react';
import Item from "../Item";
import './index.css'

class List extends Component {
    render() {

        const {todos} = this.props;

        return (
            <ul>
                {todos.map((todo) => <Item name={todo.name} key={todo.id}/>)}
            </ul>
        );
    }
}

export default List;

Item

import React, {Component} from 'react';
import './index.css'

class Item extends Component {
    render() {

        const {name} = this.props;

        return (
            <li>
                <input type="checkbox"/>
                <span>{name}</span>
                <button>删除</button>
            </li>
        );
    }
}

export default Item;

third:实现逻辑

app

import './App.css';

import React, {Component} from 'react';
import Header from "./componnents/Header";
import List from "./componnents/List";
import Footer from "./componnents/Footer";

class App extends Component {

    state = {
        todos: [
            {id: "001", name: "练习", done: false},
            {id: "002", name: "react", done: true},
            {id: "003", name: "vue", done: false}
        ]
    }

    updateTodos = (name) => {
        const uuid = require('uuid');
        const newTodo = {id: uuid.v1(), name: name, done: false};
        this.setState({todos: [...this.state.todos, newTodo]});
    }

    updateTodo = (id, done) => {
        const {todos} = this.state;
        const newTodos = todos.map((todo) => {
            if (todo.id === id) {
                todo.done = !done;
                return todo;
            } else {
                return todo;
            }
        });
        this.setState({todos: newTodos});
    }

    deleteTodo = (id) => {
        const {todos} = this.state;
        const newTodos = todos.filter((todo) => {
            return id !== todo.id
        });
        this.setState({todos: newTodos});
    }

    clearTodos = () => {
        const {todos} = this.state;
        const newTodos = todos.map((todo) => {
            todo.done = false;
            return todo;
        });
        this.setState({todos: newTodos});
    }

    checkTodos = (checked) => {
        const {todos} = this.state;
        const newTodos = todos.map((todo) => {
            todo.done = checked;
            return todo;
        });
        this.setState({todos: newTodos});
    }

    render() {

        const {todos} = this.state;

        return (
            <div>
                <Header updateTodos={this.updateTodos}/>
                <List todos={todos} deleteTodo={this.deleteTodo} updateTodo={this.updateTodo}/>
                <Footer todos={todos} clearTodos={this.clearTodos} checkTodos={this.checkTodos}/>
            </div>
        );
    }
}

export default App;

Footer

import React, {Component} from 'react';
import './index.css'

class Footer extends Component {

    handleClick = () => {
        this.props.clearTodos();
    }

    handleChange = (event) => {
        const checked = event.target.checked;
        this.props.checkTodos(checked);
    }

    render() {

        const {todos} = this.props;
        const total = todos.length;
        const doneCount = todos.reduce((pre, todo) => {
            if (todo.done === true) {
                pre += 1;
            }
            return pre;
        }, 0)

        return (
            <div>
                <input type="checkbox" onChange={this.handleChange}/>
                <span>已完成{doneCount}</span>/全部{total}
                <button onClick={this.handleClick}>清除已完成任务</button>
            </div>
        );
    }
}

export default Footer;

Header

import React, {Component} from 'react';
import './index.css'

class Header extends Component {

    handleChange = (event) => {
        const {keyCode, target} = event;
        if (keyCode !== 13 || target.value === '') {
            return;
        }
        this.props.updateTodos(target.value);
        target.value = '';
    }

    render() {
        return (
            <input type="text" placeholder="请输入你的任务名称,按回车键确认" onKeyUp={this.handleChange}/>
        );
    }
}

export default Header;

List

import React, {Component} from 'react';
import Item from "../Item";
import './index.css'

class List extends Component {
    render() {

        const {todos} = this.props;

        return (
            <ul>
                {todos.map((todo) => <Item {...todo} key={todo.id}
                                           deleteTodo={this.props.deleteTodo}
                                           updateTodo={this.props.updateTodo}/>)}
            </ul>
        );
    }
}

export default List;

Item

import React, {Component} from 'react';
import './index.css'

class Item extends Component {

    state = {mouse: false}

    handleClick = (id) => {
        this.props.deleteTodo(id);
    }

    handleCheck = (id, done) => {
        this.props.updateTodo(id, done);
    }

    mouseE = () => {
        this.setState({mouse: true});
    }

    mouseL = () => {
        this.setState({mouse: false});
    }

    render() {

        const {id, name, done} = this.props;
        const {mouse} = this.state;

        return (
            <li onMouseEnter={this.mouseE} onMouseLeave={this.mouseL}
                style={{backgroundColor: (mouse ? "#ddd" : "white")}}>
                <input type="checkbox" onChange={() => this.handleCheck(id, done)} checked={done}/>
                <span>{name}</span>
                <button onClick={() => this.handleClick(id)} style={{display: (mouse ? 'block' : 'none')}}>删除</button>
            </li>
        );
    }
}

export default Item;

这样整个逻辑代码就已经实现了,由于本人是新手,打以上代码花了差不多一天吧,虽然这次练习纯手敲并未参考,但之前已经跟着教程敲过一遍了。在练习的时候总结了一些基础知识点,如下:

  • object的key是不加引号的字符串
  • style中背景色关键字是backgroundColor
  • array.filter()是自带return的,只需要判断一下,true就返回遍历的对象
  • array.reduce(),第一个参数是function,入参有两个,第一个可认为是自定义变量,第二个是数组遍历的元素;第二个参数是function第一个入参的初始值
  • 状态提升,先写事件,事件需要操作state就写好操作函数,然后在父组件中定义该操作函数,事件中操作使用props调用该函数
  • input,需要根据输入值来判断的时候,不要使用onChange事件,使用键盘事件即onKeyUp/onKeyDown

总结:勤加练习,这样的题目至少要能纯手敲一遍


样式就不弄了,偷个懒

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值