学习视频:尚硅谷React教程(2022加更,B站超火react教程)_哔哩哔哩_bilibili
一、创建 react 应用
1、react 脚手架概述
(1)xxx 脚手架:用来帮助程序员快速创建一个基于 xxx 库的模板项目。
① 包含了所有需要的配置(语法检查、jsx编译、devServer…)。
② 下载好了所有相关的依赖。
③ 可以直接运行一个简单效果。
(2)react提供了一个用于创建react项目的脚手架库:create-react-app。
(3)项目的整体技术架构为:react + webpack + es6 + eslint。
(4)使用脚手架开发的项目的特点:模块化、组件化、工程化。
2、创建项目并启动
我是直接按照以下博客流程操作的:
React的环境搭建以及脚手架的安装 - 仰望星空的你 - 博客园
3、react 脚手架项目结构
3.1 总体架构

3.2 index.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8" /><!-- %PUBLIC_URL%代表public文件夹的路径 --><link rel="icon" href="%PUBLIC_URL%/favicon.ico" /><!-- 开启理想视口,用于做移动端网页的适配 --><meta name="viewport" content="width=device-width, initial-scale=1" /><!-- 用于配置浏览器页签+地址栏的颜色(仅支持安卓手机浏览器) --><meta name="theme-color" content="red" /><metaname="description"content="Web site created using create-react-app"/><!-- 用于指定网页添加到手机主屏幕后的图标 --><link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" /><!-- 应用加壳时的配置文件 --><link rel="manifest" href="%PUBLIC_URL%/manifest.json" /><title>React App</title></head><body><!-- 若llq不支持js则展示标签中的内容 --><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body>
</html>
二、案例:Hello,React!
1、搭建基本结构
基本结构:最重要的三个文件:index.html、App.js、index.js。
组件:最外壳的组件是:App.js,两个子组件:Hello.js、Welcome.js。

2、实现的效果

3、code
3.1 public / index.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><!-- 设置标签页的图标 --><link rel="icon" href="%PUBLIC_URL%/favicon.ico" /><title>react脚手架</title>
</head><body><div id="root"></div>
</body></html>
3.2 src / index.js
// 引入 react 核心库
import React from 'react'
// 引入 ReactDOM
// import ReactDOM from 'react-dom'
import { createRoot } from 'react-dom/client'
// 引入 App 组件
import App from './App.js'// React 18 中的更新的渲染方式写法
const con = document.querySelector('#root')
const root = createRoot(con)
root.render(<App />)
注意:
原来我们渲染组件到页面时,用的是:ReactDOM.render(...,...) ,但是在 React 18 中报错说不让使用,并给出了新的渲染方式。
// Before import { render } from 'react-dom'; const container = document.getElementById('app'); render(<App tab="home" />, container);// After import { createRoot } from 'react-dom/client'; const container = document.getElementById('app'); const root = createRoot(container); // createRoot(container!) if you use TypeScript root.render(<App tab="home" />);官方文档说明:How to Upgrade to React 18 – React Blog
3.3 src / App.js
import React from "react";
import Hello from "./Component/Hello/Hello";
import Welcome from "./Component/Welcome/Welcome";class App extends React.Component {render() {return (<div><Hello /><Welcome /></div>)}
}// 暴露 App
export default App
3.4 子组件
// Hello.jsimport React from "react";
// 引入当前路径下的 css 文件
import './Hello.css'export default class Hello extends React.Component {render() {return <h2 className="hello">Hello!我是第一个组件哈!</h2>}
}
/* Hello.css */.hello {background-color: antiquewhite;
}
三、案例:增删改列表
1、实现的效果

2、code
具体的 code 实现放上来有点多,我放在资源里,可自行下载(这个是自己敲的,有些小细节可能不同),也可以参考学习视频里面老师的做法自己实现。
react的todoList案例代码-Javascript文档类资源-CSDN下载
3、实现案例后的总结
3.1 动态初始化列表,如何确定将数据放在那个组件的 state 中?
(1)某个组件使用:放在其自身的 state 中。
(2)某些组件使用:放在他们共同的父组件 state 中(官方称为:状态提升)。在这个案例中,整体列表的 state 都放在 APP.js 中。
(3)状态在哪里,操作状态的方法就在哪里。所以增删改的方法都放在 APP.js 中(addTodos、updateTodos、deleteTodos)。
3.2 关于父子组件之间的通信
(1)父组件 ==> 子组件 传递数据:通过 props 传递。
<!-- 父组件给子组件传递数据 -->
<List todos={todos} updateTodos={this.updateTodos} deleteTodos={this.deleteTodos} /><!-- 子组件接收数据 -->
const { todos, updateTodos, deleteTodos } = this.props
(2)子组件 ==> 父组件 传递数据:父组件通过 props 提前给子组件传递一个函数,子组件通过调用这个函数完成数据传递。
<!-- 父组件给子组件传递一个函数 -->
<Footer todos={todos} changeChecked={this.changeChecked} /><!-- 子组件调用这个函数 -->
changeChecked = (event) => {this.props.changeChecked(event.target.checked)
}
3.3 数组方法:Array.prototype.reduce()
reduce() 方法对数组中的每个元素按序执行一个由您提供的 reducer 函数,每一次运行 reducer 会将先前元素的计算结果作为参数传入,最后将其结果汇总为单个返回值。
// 官方示例
const array1 = [1, 2, 3, 4];// 0 + 1 + 2 + 3 + 4
const initialValue = 0;
const sumWithInitial = array1.reduce((previousValue, currentValue) => previousValue + currentValue,initialValue
);console.log(sumWithInitial);
// expected output: 10
// 案例中计算已完成个数
const finishedTodos = todos.reduce((pre, todo) => pre + (todo.done ? 1 : 0), 0)
官方文档:Array.prototype.reduce() - JavaScript | MDN
3.4 数组方法(遍历):Array.prototype.map()
map() 方法创建一个新数组,这个新数组由原数组中的每个元素都调用一次提供的函数后的返回值组成。
callback 生成新数组元素的函数,使用三个参数:
(1)currentValue:callback 数组中正在处理的当前元素。
(2)index(可选):callback 数组中正在处理的当前元素的索引。
(3)array(可选):map 方法调用的数组。
// 官方示例
const array1 = [1, 4, 9, 16];// pass a function to map
const map1 = array1.map(x => x * 2);console.log(map1);
// expected output: Array [2, 8, 18, 32]
// 案例中使用
const newTodos = todos.map((todoObj) => {return { ...todoObj, done: done }
})
官方文档:Array.prototype.map() - JavaScript | MDN
3.5 数组方法(过滤):Array.prototype.filter()
filter() 方法创建一个新数组,其包含通过所提供函数实现的测试(满足条件)的所有元素。
// 官方示例
const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];const result = words.filter(word => word.length > 6);console.log(result);
// expected output: Array ["exuberant", "destruction", "present"]
// 案例中使用const newTodos = todos.filter((todoObj) => {return !todoObj.done
})
3.6 增删改基本操作
方法基本步骤是:获取状态、对数据进行增删改操作,更新状态。
addTodos = (todoObj) => {// 获取原来的 todosconst { todos } = this.state// 创建新的 todo,注意这里是一个数组!const newTodo = [todoObj, ...todos]// 更新状态this.setState({ todos: newTodo })}
















