React 入门

前言

最近接手一个 React 项目,还是大屏展示的,似乎还挺简单的,但是也不太会 React,所以有了这篇文章,我还在努力学 vue 呢,哎突然插进来这个,哈哈哈。


介绍

官方介绍,似乎来源于 facebook


新建并启动项目

在命令行里输入如下命令

1
npx create-react-app hello-react

什么是 npx 呢? 可以看一下阮一峰的教程
主要点:

  • Node 自带 npm 模块,所以可以直接使用 npx 命令。万一不能用,就要手动安装一下
  • npx 想要解决的主要问题,就是调用项目内部安装的模块
  • 避免安装全局模块

安装过程如下(我网络比较慢…)
请添加图片描述
安装好后,cd 到你的项目下,然后执行 npm run start 即可启动项目。


create-react-app 项目结构

创建好后的项目如下
在这里插入图片描述
有些比较常见,下面是 react 项目比较重要的文件说明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

├── README.md 文档
├── public 静态资源
│ ├── favicon.ico
│ ├── index.html
│ └── manifest.json
└── src 源码
├── App.css
├── App.js 根组件
├── App.test.js
├── index.css 全局样式
├── index.js 入口文件
├── logo.svg
└── serviceWorker.js pwa 支持
├── package.json npm 包依赖

执行如下命令配置暴露项:

1
npm run eject

执行后,项目目录会新增加 config 以及 script 文件夹
在这里插入图片描述


React 和 ReactDOM

可以在 scr/index.js 目录下查看相关代码
在这里插入图片描述

  • React负责逻辑控制,数据 -> VDOM
  • ReactDom渲染实际DOM,VDOM -> DOM
  • React使⽤用JSX来描述UI
  • babel-loaderJSX 编译成相应的 JS 对象
  • React.createElement再把这个 JS对象构造成 React 需要的虚拟dom
  • babel-loaderJSX 编译成相应的 JS 对象,React.createElement再把这个JS对象构造成React
    要的 虚拟dom

JSX 语法

在这里插入图片描述

JSX 是⼀种 JavaScript 的语法扩展,其格式比较像模版语言,但事实上完全是在JavaScript内部实现的。

基本使⽤

表达式{}的使⽤

在这里插入图片描述


函数

函数也是合法表达式

1
2
3
4
5
6
7
8
9
10
const obj = {
fistName: "王",
lastName: "先生",
};
function formatName(name) {
return name.fistName + " " + name.lastName;
}
const jsx = <div>{formatName(obj)}</div>;

ReactDOM.render(jsx, document.getElementById("root"));

如果直接要展示对象的话,会报错

在这里插入图片描述


jsx 对象

1
2
3
4
5
6
7
8
const jsxObject = <div>我是 jsx 对象</div>;
const jsx = (
<div>
<div>{jsxObject}</div>
</div>
);

ReactDOM.render(jsx, document.getElementById("root"));

在这里插入图片描述


条件表达

三目运算符!

在这里插入图片描述
或者是 &&这样


数组

想要循环数组的话可以这么干
在这里插入图片描述

注意:

  • li 需要添加 key 属性,不然会报错

    在这里插入图片描述

  • 如果是 forEach 的话就不行了,因为 map 是返回新的数组,forEach 啥都不返回

    在这里插入图片描述


添加属性

也是通过表达式

src 属性

这里给 img 标签添加 src 属性
在这里插入图片描述


元素类名

在添加一个 class 属性,通过 className 来添加
在这里插入图片描述


行内 Style

首先是 style 属性,用表达式包上一层{}
然后里面写个对象,所以又有一层{}
在这里插入图片描述


CSS 模块化

css 的模块化如下图所示,类名自动帮你改了,防止重复,对于大型项目来说是有用的
在这里插入图片描述

也可以安装一下 sass,用于写 .scss 文件

1
npm install sass -D

VScode 插件

这里推荐一个 vscode 的插件,用于快速构建基础代码 Reactjs code snippets

在这里插入图片描述

比方说构一个 Class 组件 rccFunction组件rfc

请添加图片描述

然后,写状态:con ,之后sst 设置状态
请添加图片描述


组件

组件,从概念上类似于 JavaScript 函数。有两种形式:class组件和function组件。

Class 组件

基础结构

首先新建一个 page 文件夹,然后新建 js 文件,里面的内容如下

1
2
3
4
5
6
7
8
9
10
import React, { Component } from "react";
export default class ClassComponent extends Component {
render() {
return (
<div>
<h3>i am ClassComponent</h3>
</div>
);
}
}

然后再主入口文件中引入一下

在这里插入图片描述


Class 实例:时钟(组件属性、声明周期)

在构造函数constructor中设置组件的属性

这里使用到了componentDidMount 这个声明周期

整体的思路如下:

在这里插入图片描述


代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import React, { Component } from "react";

export default class ClassComponents extends Component {
constructor(props) {
super(props);
// 使⽤用state属性维护状态,在构造函数中初始化状态
this.state = {
date: new Date(),
};
}
// react 的生命周期
// 组件加载完后会执行
componentDidMount() {
// 使⽤用setState⽅方法更更新状态
this.timer = setInterval(() => {
this.setState({
date: new Date(),
});
}, 1000);
}
// 组件卸载之前执行
componentWillUnmount() {
console.log("componentWillUnmount");
clearInterval(this.timer);
}
componentDidUpdate() {
console.log("componentDidUpdate");
}
render() {
const { date } = this.state;
return (
<div>
<span>{date.toLocaleTimeString()}</span>
</div>
);
}
}

Function 组件

函数组件通常⽆无状态,仅关注内容展示,返回渲染结果即可

从 React16.8 开始引⼊入了了 hooks,函数组件也能够拥有状态。

function 组件创建⼀个Clock

在这里插入图片描述
代码执行后如下图所示:
请添加图片描述


关于 setState

正确使用 setState

1
setState(partialState, callback);
  • partialState:object|function 用于产生与当前 state 合并的⼦集。
  • callback:function state更新之后被调⽤

关于 setState() 你应该了解三件事

不要直接修改 State

首先,直接修改的话会提示你
在这里插入图片描述

而且直接修改的话也不会更新组件

1
2
3
4
5
6
7
// 错误示范
this.state.date = new Date();

// 正确示范
this.setState({
date: new Date(),
});
State 的更新可能是异步的

出于性能考虑,React 可能会把多个 setState() 调⽤合并成一个调⽤。 观察以下例子中log的值和button显示的counter
请添加图片描述

如果要获取到最新状态值有以下方式:

  • 在回调中获取状态值
    请添加图片描述

  • 使⽤定时器
    请添加图片描述

  • 原生事件中修改状态
    请添加图片描述


State 的更新会被合并

先看一下被合并的情况
请添加图片描述

那要怎么解决呢,还记得 setState() 的第一个参数可以传递函数吗!

请添加图片描述

或者这样

1
2
3
4
5
6
7
changeValue = (v) => {
this.setState((state) => ({ counter: state.counter + v }));
};
setCounter = () => {
this.changeValue(1);
this.changeValue(2);
};

生命周期

16.4 版本之前的生命周期

找了一张图啊,先放这儿。
在这里插入图片描述

然后我就实验一下呗!

mounted 好实验,update 需要更新一下数据才能触发生命周期钩子,所以这里我在componentWillMount中写了个延时定时器

请添加图片描述

  • componentWillUnmount 组件将要卸载时触发,可以用于取消定时器之类的操作请添加图片描述
  • componentWillReceiveProps :组件初次渲染时不会触发,只有已挂载的组件接收新的 props 的时候才会执行。
    请添加图片描述

16.4 版本之后的生命周期

这个网站有生命周期的概述。
在这里插入图片描述

被废弃的生命周期

V17可能会废弃的三个⽣生命周期函数⽤用getDerivedStateFromProps替代,

  • componentWillMount
  • componentWillReceiveProps
  • componentWillUpdate

⽬前使用的话加上 UNSAFE_,否则会报 Warning在这里插入图片描述
如果不想⼿动给将要废弃的生命周期添加 UNSAFE_ 前缀,可以⽤下⾯的命令。

1
npx react-codemod rename-unsafe-lifecycles <path>

初次使用这个命令会安装一个依赖 react-codemod

请添加图片描述

安装完依赖之后再次执行该命令即可。

在这里插入图片描述

新引入的生命周期

新引⼊的两个生命周期函数

  • getDerivedStateFromProps:会在调⽤ render ⽅法之前调用,并且在初始挂载及后续更新时都会被
    调用,它应返回一个对象来更新 state,如果返回 null 则不更新任何内容。(这个跟原先 unsafe 的生命周期是冲突的,不能共用!)
  • getSnapshotBeforeUpdate:在render之后,在componentDidUpdate之前。