[尚硅谷React笔记]——第3章 React应用(基于React脚手架)

news/2024/7/15 17:34:20 标签: react.js, 笔记, javascript

目录:

  1. react脚手架
  2. 创建项目并启动
  3. react脚手架项目结构
  4. 一个简单的Hello组件
  5. 样式的模块化
  6. 功能界面的组件化编码流程(通用)
  7. 组件的组合使用-TodoList  

1.react脚手架

  1. xxx脚手架: 用来帮助程序员快速创建一个基于xxx库的模板项目
    1. 包含了所有需要的配置(语法检查、jsx编译、devServer…)
    2. 下载好了所有相关的依赖
    3. 可以直接运行一个简单效果
  2. react提供了一个用于创建react项目的脚手架库: create-react-app
  3. 项目的整体技术架构为:  react + webpack + es6 + eslint
  4. 使用脚手架开发的项目的特点: 模块化, 组件化, 工程化

2.创建项目并启动

  1. 全局安装:npm i -g create-react-app
  2. 切换到想创项目的目录,使用命令:create-react-app hello-react
  3. 进入项目文件夹:cd hello-react
  4. 启动项目:npm start

3.react脚手架项目结构

public ---- 静态资源文件夹

                        favicon.icon ------ 网站页签图标

                        index.html -------- 主页面

                        logo192.png ------- logo

                        logo512.png ------- logo

                        manifest.json ----- 应用加壳的配置文件

                        robots.txt -------- 爬虫协议文件

src ---- 源码文件夹

                        App.css -------- App组件的样式

                        App.js --------- App组件

                        App.test.js ---- 用于给App做测试

                        index.css ------ 样式

                        index.js ------- 入口文件

                        logo.svg ------- logo

                        reportWebVitals.js --- 页面性能分析文件(需要web-vitals库的支持)

                        setupTests.js ---- 组件单元测试的文件(需要jest-dom库的支持)

4.一个简单的Hello组件

Hello.jsx

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

export default class Hello extends Component {
    render() {
        return <h2 className="title">hello,react!</h2>
    }
}

Hello.css

.title {
    background-color: orange;
}

Welcome.jsx

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

export default class Welcome extends Component {
    render() {
        return <h2 className="demo">welcome</h2>
    }
}

Welcome.css

.demo {
    background-color: skyblue;
}

 App.js

import React from 'react'
import Hello from "./components/Hello/Hello";
import Welcome from "./components/Welcome/Welcome";

export default class App extends React.Component {
    render() {
        return (
            <div>
                <Hello></Hello>
                <Welcome></Welcome>
            </div>
        )
    }
}

index.js

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

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App/>);

 运行结果:

5.样式的模块化 

Hello.jsx

import React, {Component} from 'react'
import hellocss from './Hello.module.css'

export default class Hello extends Component {
    render() {
        return <h2 className={hellocss.title}>hello,react!</h2>
    }
}

Hello.module.css

.title {
    background-color: orange;
}

 Welcome.jsx

import React, {Component} from "react";
import welcomecss from './Welcome.module.css'

export default class Welcome extends Component {
    render() {
        return <h2 className={welcomecss.title}>welcome</h2>
    }
}

Welcome.module.css

.title {
    background-color: skyblue;
}

 运行结果:

6.功能界面的组件化编码流程(通用)

  1. 拆分组件: 拆分界面,抽取组件
  2. 实现静态组件: 使用组件实现静态页面效果
  3. 实现动态组件
    1. 动态显示初始化数据
      1. 数据类型
      2. 数据名称
      3. 保存在哪个组件?
    2. 交互(从绑定事件监听开始)

7.组件的组合使用-TodoList  

todoList案例相关知识点

  1. 拆分组件、实现静态组件,注意: className、style的写法
  2. 动态初始化列表,如何确定将数据放在哪个组件的state中?
    1. 某个组件使用放在自身的state中
    2. 某些组件使用:放在他们共同的父组件state中(官方称此操作为:状态提升
  3. 关于父子之间通信:
    1. 【父组件】给【子组件】传递数据:通过props传递
    2. 【子组件】给【父组件】传递数据:通过props传递,要求父提前给子传递
  4. 注意defaultchecked 和 checked的区别,类似的还有: defaultValue 和 value
  5. 状态在哪里,操作状态的方法就在哪里

 Footer.css

/*footer*/
.todo-footer {
    height: 40px;
    line-height: 40px;
    padding-left: 6px;
    margin-top: 5px;
}

.todo-footer label {
    display: inline-block;
    margin-right: 20px;
    cursor: pointer;
}

.todo-footer label input {
    position: relative;
    top: -1px;
    vertical-align: middle;
    margin-right: 5px;
}

.todo-footer button {
    float: right;
    margin-top: 5px;
}

Footer.jsx

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

class Footer extends Component {
    handleCheckAll = (event) => {
        this.props.checkAllTodo(event.target.checked)
    }
    handleClearAllDone = () => {
        this.props.clearAllDone()
    }


    render() {
        const {todos} = this.props
        const doneCount = todos.reduce((pre, current) => {
            return pre + (current.done ? 1 : 0)
        }, 0)
        const total = todos.length
        return (
            <div className="todo-footer">
                <label>
                    <input type="checkbox" onChange={this.handleCheckAll}
                           checked={doneCount === total && total !== 0 ? true : false}/>
                </label>
                <span>
                    <span>已完成{doneCount}</span> / 全部{total}
                </span>
                <button onClick={this.handleClearAllDone} className="btn btn-danger">清除已完成任务</button>
            </div>
        );
    }
}

export default Footer;

Header.css

/*header*/
.todo-header input {
    width: 560px;
    height: 28px;
    font-size: 14px;
    border: 1px solid #ccc;
    border-radius: 4px;
    padding: 4px 7px;
}

.todo-header input:focus {
    outline: none;
    border-color: rgba(82, 168, 236, 0.8);
    box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
}

Header.jsx

import React, {Component} from 'react';
import PropTypes from 'prop-types'
import {nanoid} from "nanoid";
import './Header.css'

class Header extends Component {
    static propTypes = {
        addTodo: PropTypes.func.isRequired
    }

    handleKeyUp = (event) => {
        const {keyCode, target} = event
        if (keyCode != 13) return
        if (target.value.trim() == '') {
            alert('输入不能为空')
            return;
        }
        const todoObj = {id: nanoid(), name: target.value, done: false}
        this.props.addTodo(todoObj)

        target.value = ''
    }

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

export default Header;

Item.css

/*item*/
li {
    list-style: none;
    height: 36px;
    line-height: 36px;
    padding: 0 5px;
    border-bottom: 1px solid #ddd;
}

li label {
    float: left;
    cursor: pointer;
}

li label li input {
    vertical-align: middle;
    margin-right: 6px;
    position: relative;
    top: -1px;
}

li button {
    float: right;
    display: none;
    margin-top: 3px;
}

li:before {
    content: initial;
}

li:last-child {
    border-bottom: none;
}

Item.jsx

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

class Item extends Component {
    state = {mouse: false}

    handelMouse = (flag) => {
        return () => {
            this.setState({mouse: flag})
        }
    }

    handleCheck = (id) => {
        return (event) => {
            this.props.updateTodo(id, event.target.checked)
        }
    }

    handleDelete = (id) => {
        if (window.confirm('确定删除吗?')) {
            this.props.deleteTodo(id)
        }
    }

    render() {
        const {id, name, done} = this.props
        const {mouse} = this.state
        return (
            <li style={{backgroundColor: mouse ? '#ddd' : 'white'}} onMouseEnter={this.handelMouse(true)}
                onMouseLeave={this.handelMouse(false)}>
                <label>
                    <input type="checkbox" checked={done} onChange={this.handleCheck(id)}/>
                    <span>{name}</span>
                </label>
                <button onClick={() => {
                    this.handleDelete(id)
                }}
                        className="btn btn-danger"
                        style={{display: mouse ? 'block' : 'none'}}>删除
                </button>
            </li>
        );
    }
}

export default Item;

List.css

/*main*/
.todo-main {
    margin-left: 0px;
    border: 1px solid #ddd;
    border-radius: 2px;
    padding: 0px;
}

.todo-empty {
    height: 40px;
    line-height: 40px;
    border: 1px solid #ddd;
    border-radius: 2px;
    padding-left: 5px;
    margin-top: 10px;
}

List.jsx

import React, {Component} from 'react';
import PropTypes from "prop-types";
import Item from "../Item/Item";
import './List.css'


class List extends Component {
    static propTypes = {
        todos: PropTypes.array.isRequired,
        updateTodo: PropTypes.func.isRequired,
        deleteTodo: PropTypes.func.isRequired
    }

    render() {
        const {todos, updateTodo, deleteTodo} = this.props
        return (
            <ul className="todo-main">
                {
                    todos.map((todo) => {
                        return <Item key={todo.id} {...todo} updateTodo={updateTodo} deleteTodo={deleteTodo}></Item>
                    })
                }
            </ul>
        );
    }
}

export default List;

App.css

/*base*/
body {
    background: #fff;
}

.btn {
    display: inline-block;
    padding: 4px 12px;
    margin-bottom: 0;
    font-size: 14px;
    line-height: 20px;
    text-align: center;
    vertical-align: middle;
    cursor: pointer;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
    border-radius: 4px;
}

.btn-danger {
    color: #fff;
    background-color: #da4f49;
    border: 1px solid #bd362f;
}

.btn-danger:hover {
    color: #fff;
    background-color: #bd362f;
}

.btn:focus {
    outline: none;
}

.todo-container {
    width: 600px;
    margin: 0 auto;
}

.todo-container .todo-wrap {
    padding: 10px;
    border: 1px solid #ddd;
    border-radius: 5px;
}








App.js

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

class App extends Component {
    //初始化状态
    state = {
        todos: [
            {id: '001', name: '吃饭', done: true},
            {id: '002', name: '睡觉', done: true},
            {id: '003', name: '打代码', done: false},
            {id: '004', name: '逛街', done: true},
        ]
    }

    addTodo = (todoObj) => {
        const {todos} = this.state
        const newTodos = [todoObj, ...todos]
        this.setState({todos: newTodos})
    }

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

        this.setState({todos: newTodos})
    }

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

    checkAllTodo = (done) => {
        const {todos} = this.state
        const newTodos = todos.map((todoObj) => {
            return {...todoObj, done: done}
        })
        this.setState({todos: newTodos})
    }

    clearAllDone = () => {
        const {todos} = this.state
        const newTodos = todos.filter((todoObj) => {
            return !todoObj.done
        })
        this.setState({todos: newTodos})
    }

    render() {
        return (
            <div className="todo-container">
                <div className="todo-wrap">
                    <Header addTodo={this.addTodo}></Header>
                    <List todos={this.state.todos} updateTodo={this.updateTodo} deleteTodo={this.deleteTodo}></List>
                    <Footer todos={this.state.todos}
                            checkAllTodo={this.checkAllTodo}
                            clearAllDone={this.clearAllDone}>
                    </Footer>
                </div>
            </div>
        );
    }
}

export default App;

index.js

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

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App/>);

项目结构:

运行结果:

 


http://www.niftyadmin.cn/n/5068282.html

相关文章

【Java】main方法的深入理解

目录 深入理解 main 方法 public static void main(String[] args) ​编辑示例代码&#xff1a; 编译运行&#xff08;String[] args&#xff09;&#xff1a; main 方法的注意事项 示例代码&#xff1a; 深入理解 main 方法 public static void main(String[] args) mai…

linux基础内功2--- 互斥与并发

1、同步、异步、堵塞和非堵塞 并发:多个进程同时运行,即为并发。 互斥:分布在不同进程之间的若干个程序片段,规定当某个进程运行其中一个程序片段时,其他进程不能运行它们之中任一个程序片段,只能等到该进程运行完这个程序片段后才能开始运行。同一资源同个时间只有一个…

小程序如何使用自定义组件

使用自定义组件的步骤如下&#xff1a; 创建自定义组件&#xff1a;在小程序项目根目录下的 components 文件夹中创建一个文件夹&#xff0c;然后在该文件夹中创建一个 .json 文件、一个 .wxml 文件和一个 .js 文件&#xff0c;这三个文件分别对应组件的配置、模板和逻辑。 在…

pip国内镜像下载网站方法

镜像下载网站 1.清华源 https://pypi.tuna.tsinghua.edu.cn/simple2.阿里源 http://mirrors.aliyun.com/pypi/simple/3.中科大源 https://pypi.mirrors.ustc.edu.cn/simplepip下载方式&#xff1a; pip install 包名版本号 -i https://pypi.tuna.tsinghua.edu.cn/simple注…

React核心原理与实际开发

学习目标 React是啥&#xff1f; 官方定义&#xff1a;将前端请求获取到的数据渲染为HTML视图的JavaScript库。 一、React入门 1、React项目创建 直接创建react&#xff0c;使用初始化会创建package.json npm init -y再安装 2、React基本使用 使用纯JS创建ReactDOM&#…

国庆中秋宅家自省: 低维认知是方法论|高维认知是能量场

Python3中类的高级语法及实战 Python3(基础|高级)语法实战(|多线程|多进程|线程池|进程池技术)|多线程安全问题解决方案 Python3数据科学包系列(一):数据分析实战 Python3数据科学包系列(二):数据分析实战 Python3数据科学包系列(三):数据分析实战 国庆中秋宅家自省: Pytho…

【一、灵犀考试系统项目设计、框架搭建】

一、创建数据库 1、打开power designer&#xff0c;新建数据库模型 2、新建数据表&#xff0c;以及关系 【注意】 图片的类型有两种&#xff1a;varbinary 和 image varbinary : 二进制字节流&#xff0c;可以自动控制长度 image : 最大可放2G图片 3、创建数据库&#…

[C]嵌入式中变量存储方案

#include<stdio.h>#define uint8_t unsigned char #define uint16_t unsigned short #define uint24_t unsigned int #define uint32_t unsigned int #define uint64_t unsigned long long//用户自定义变量名字&#xff0c;用于存储 typedef enum {first_run 0,//…