React 的学习笔记一 (未完结)
一、React 是什么
React 是一个声明式,高效且灵活的用于构建用户界面的 JavaScript 库。使用 React 可以将一些简短、独立的代码片段组合成复杂的 UI 界面,这些代码片段被称作“组件”。
1.1、React的优点
采用组件化模式,声明式编程( react是面向数据编程,不需要直接去控制dom,你只要把数据操作好,react自己会去帮你操作dom,可以节省很多操作dom的代码。这就是声明式开发),提高开发效率与组件复用率;
- 在 React Native 中可以使用 React 语法进行移动端开发;
通过虚拟DOM + Diffing算法,最大限度的减少与DOM的交互,速度很快;
使用JSX,代码可读性很好;
React 可以与已有的库或者框架很好的配合;
使用 React 构建组件使代码更加容易得到复用,可以很好的应用在大项目的开发过程中;
其单向数据流减少了重复的代码,轻松实现数据绑定。
1.2、React的缺点
React 不适合单独做一个完整的框架,做大型项目需要和其他框架组合使用
React 的库非常庞大,新手很难理解需要花费一定的时间,使用内联模板和JSX,使编码变得复杂
1.3、React 与 Vue 的区别
理念差异:
从设计理念上来说,vue更像是一种模板引擎。所谓模板引擎就是在静态模板上动态替换 Js 变量,最终渲染出页面。一个vue文件中,有html、css、js,放在一起。很直观,html 是静态模板,js 是动态变量。vue 在模板引擎的基础上加了很多 v 指令,大大简化了开发。但是当 js 逻辑很复杂的时候,状态管理变得很麻烦。
而对于React来说,React受函数式编程的影响,将 html 视为数据映射的结果,一个数据映射一个 html ,组合起来就是一个完整的页面DOM树。这则是区别于“ 模板思维”的“映射思维”。这是React与Vue最核心的差异。
对于 vue 来说,html 是首位,vue 中的 html 模板已经算是一个近乎完整的页面,只不过有几个变量无法确定,再把 js 加上去就好。而对于 React 来说,Js 是首位,有 Js 才有 html,Js 是因,html 是果。
共同点:
虚拟Dom:改变真实的DOM状态远比改变一个JavaScript对象的花销要大得多。 Virtual DOM是一个映射真实 DOM 的 JavaScript 对象,如果需要改变任何元素的状态,那么是先在 Virtual DOM 上进行改变,而不是直接改变真实的 DOM。当有变化产生时,一个新的 Virtual DOM 对象会被创建并计算新旧 Virtual DOM 之间的差别。之后这些差别会应用在真实的 DOM上。这极大的提高了性能。
组件化:vue 和 react 都建议将应用拆分成多个组件,每个组件负责不同的工作,组件之间通过特殊的方式相互关联。使应用的结构变得清晰,也有利于组件复用。
区别:
Vue 建议使用 html 模板进行编写,而 React 则使用了Javascript 的扩展语法 —— JSX,赋予了开发者许多变成能力。
React 应用中的状态是(React)关键的概念。也有一些配套框架被设计为管理一个大的 state 对象,如 Redux。此外,state 对象在 React 应用中是不可变的,意味着它不能被直接改变(这也许不一定正确)在 React 中你需要使用 setState() 方法去更新状态。
在 vue中,数据由 data 属性在 Vue 对象中进行管理。data 参数就是应用中数据的保存者。 对于管理大型应用中的状态这一话题而言,Vue 解决方案适用于小型应用,但对于对于大型应用而言不太适合。
第一标题的原文链接:https://blog.csdn.net/qq_45643079/article/details/119914443
二、React 的实现
第一次渲染数据的时候,会在Virtual-Dom里面进行比较,如果没有找到相同 DOM 就会创建一个新的虚拟DOM,然后就渲染到页面真实 DOM 重排页面元素,如果对比有相同虚拟DOM 就会复用该虚拟DOM,页面元素不会重排。
原本数组里面有2条数据,展示后虚拟 DOM 就会创建这两个数据<li>的虚拟DOM ,此时添加一条新的数据,这时候数组就会有三条数据,前面两条数据在第一次对比的时候就已经创建虚拟DOM了,前两条数据对比相同就不会渲染,而新添加的第三条数据,对比内存没有相对应的虚拟DOM,则创建新的虚拟DOM ,再重新渲染到页面上!

2.0、创建 react 项目
2.0.1、使用脚手架创建
创建命令:
npx create-react-app 项目名
2.0.2、使用 vite 创建
创建命令:
npm create vite@latest
选择 React !!!
2.0.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库的支持)
2.1、使用 react 输出 “ hello,react ” 案例
实现代码:
<!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">
<title>hello-react</title>
</head>
<body> <!-- 容器 -->
<div id="test"></div> <!-- 引用的时候,一定要注意先后顺序!!! -->
<!-- react:react核心库 -->
<script type="text/javascript" src="./js/react.development.js"></script>
<!-- react-dom:用于支持react操作DOM元素 -->
<script type="text/javascript" src="./js/react-dom.development.js"></script>
<!-- babel:用于将jsx转换为js -->
<script type="text/javascript" src="./js/babel.min.js"></script> <!-- 请注意!! 这里一定要写babel -->
<script type="text/babel">
// 1、创建虚拟DOM
const VDDM = <h1>hello,react</h1> /* 这里一定不要写单引号,因为不是字符串 */
// 2、渲染虚拟DOM到页面里,使用ReactDOM.render(虚拟DOM,容器);
ReactDOM.render(VDDM,document.getElementById("test"));
// 请注意,我想再这个容器里面再写一句话
// const VDDM2 = <h1>hello,react</h1>
// ReactDOM.render(VDDM2,document.getElementById("test")); // 这个是失败的,因为它不是追加,而是覆盖 </script>
</body>
</html>
运行结果:

2.2、虚拟DOM 的两种创建方法,并使用多级层次结构
2.2.1、使用 jsx 来创建虚拟 DOM
实现代码:
<!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">
<title></title>
</head>
<body> <!-- 容器 -->
<div id="test"></div> <!-- 引用的时候,一定要注意先后顺序!!! -->
<!-- react:react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- react-dom:用于支持react操作DOM元素 -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- babel:用于将jsx转换为js -->
<script type="text/javascript" src="../js/babel.min.js"></script> <!-- 请注意!! 这里一定要写babel -->
<script type="text/babel">
// 1、创建虚拟DOM
const VDDM = (
<h1 id="title">
<span>hello,react</span>
</h1>
) /* 这里一定不要写单引号,因为不是字符串 */
// 2、渲染虚拟DOM到页面里,使用ReactDOM.render(虚拟DOM,容器);
ReactDOM.render(VDDM,document.getElementById("test")); </script>
</body>
</html>
2.2.2、使用 js 来创建虚拟 DOM
实现代码:
<!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">
<title></title>
</head>
<body> <!-- 容器 -->
<div id="test"></div> <!-- 引用的时候,一定要注意先后顺序!!! -->
<!-- react:react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- react-dom:用于支持react操作DOM元素 -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- 不需要引入 babel --> <!-- 请注意!! 这里改为javascipt -->
<script type="text/javascript">
// 1、创建虚拟DOM,创建节点:React.createElement("标签名","标签属性","标签内容")
const VDDM = React.createElement("h1",{id: "title",class: "titles"},React.createElement("span",{},"Hello,React"));
// 2、渲染虚拟DOM到页面里,使用ReactDOM.render(虚拟DOM,容器);
ReactDOM.render(VDDM,document.getElementById("test")); </script>
</body>
</html>
运行结果:

2.3、虚拟DOM与真实DOM
虚拟DOM:
const VDDM = (
<h1 id="title">
<span>hello,react</span>
</h1>
)
document.getElementById("test");
1.本质是Object类型的对象(是一般对象)
2.虚拟DOM比较“轻”,真实DOM比较“重”,因为虚拟DOM是React内部在用,无需真实DOM上那么多的属性。
3.虚拟DOM最终会被React转换为真实DOM,呈现在页面上。
4.它是运行在内存里面的。
2.4、jsx 概要
JSX 是 Javascript 的一种语法拓展
JSX是 JavaScript XML 简写,表示在 JavaScript 中编写XML格式代码(也就是HTML格式)
2.4.1、jsx的优点
声明式语法更加直观
与HTML结构相同
降低了学习成本、提升开发效率
注意:JSX 并不是标准的 JS 语法,是 JS 的语法扩展,浏览器默认是不识别的,脚手架中内置的 @babel/plugin-transform-react-jsx 包,用来解析该语法的!
2.4.2、jsx语法规则
1.定义虚拟DOM时,不要写引号;
2.标签中混入JS表达式时使用{};
3.样式的类名指定不要用class,要用className,属性名采用驼峰命名法 class -> className,for -> htmlFor
4.内联样式,要用style={{ key:value }}的形式去写
5.虚拟DOM只有一个根标签,如果没有根节点,可以使用 <></>(幽灵节点)替代
6.标签必须闭合(input、img标签)成对闭合或者自闭合都可以
7.标签首字母
(1)如果小写字母开头,则将改标签转为html中的同名元素,如果html中没有该标签对应的同名元素,则报错
(2)如果大写字母开头,react就去渲染对应的组件,如果组件没有定义,则报错
8.JSX支持多行(换行),如果需要换行,需使用() 包裹,防止bug出现
2.4.3、jsx的练习 — 动态展示列表数据
2.4.3.1、区分js语句(例如 if 判断、for 循环)与 js 表达式
1.表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方
表达式栗子:
以下的表达式都可以用一个变量来接收它返回的值
(1)a // 这个可以是一个变量名
(2)a+b // 加法表达式
(3)demo(1) // 这个是函数调用表达式
(4)arr.map()
(5)function.test(){}
2.语句:控制代码走向,并没有返回值
语句的栗子:
(1)if(){}
(2)for(){}
(3)switch(){case: xxx}
2.4.3.2、代码实现
代码如下:
<!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" />
<title>1</title>
</head>
<body>
<!-- 容器 -->
<div id="test"></div> <!-- react:react核心库 -->
<script type="text/javascript" src="../js/react.development.js"></script>
<!-- react-dom:用于支持react操作DOM元素 -->
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<!-- babel:用于将jsx转换为js -->
<script type="text/javascript" src="../js/babel.min.js"></script> <script type="text/babel">
// 模拟后端传过来的数据
const data = ['Angular','React','Vue']
// 创建虚拟DOM
const VDOM = (
<div>
<h1>前端js框架列表</h1>
<ul>
{
// 加工数组,key是虚拟DOM的唯一标识符
data.map((item,index)=>{
return <li key={index}>{item}</li>
})
}
</ul>
</div>
) // 渲染
ReactDOM.render(VDOM,document.getElementById("test")) </script>
</body>
</html>
运行结果:

三、组件(Component)
如果我们将一个页面中所有的处理逻辑全部放在一起,处理起来就会变得非常复杂,而且不利于后续的管理以及扩展,但如果,我们将一个页面拆分成一个个小的功能块,每个功能块完成属于自己这部分独立的功能,那么之后整个页面的管理和维护就变得非常容易了。如果我们将一个个功能块拆分后,就可以像搭建积木一下来搭建我们的项目。它接受任意的入参(即 “props”),并返回用于描述页面展示内容的 React 元素。
理解:用来实现局部功能效果的代码和资源的集合(html / css / js / image 等等)
为什么要用组件: 一个界面的功能更复杂
作用:复用编码, 简化项目编码, 提高运行效率

3.1、使用 class 定义组件,叫类样式组件
使用 class 定义组件需要满足两个条件:
class 继承自 React.Component
class 内部必须定义 render 方法,rende r方法返回代表该组件 UI 的 React 元素
栗子如下:
使用脚手架新建一个简易BBS项目,在这个项目中定义一个组件 PostList,用于展示BBS 的帖子列表;定义一个 PostItem,用于接收父组件传来的值,渲染到页面上
PostList 代码如下:
import React, { Component } from 'react'
import PostItem from './PostItem'
export class PostList extends Component {
render() {
const data = [
{title: "重磅!党和国家机构改革有新进展",author: "小明",date: "2023-03-01"},
{title: "美环保署前负责人:“毒火车”脱轨地区的环境显然有问题",author: "小虎",date: "2022-01-11"},
{title: "中央网信办所属部分在京事业单位2023年度公开招聘公告",author: "小钰",date: "2021-02-12"},
{title: "北京网络辟谣 互联网联合辟谣平台 网络辟谣标签工作专区",author: "小欧",date: "2011-12-12"}
]
return (
<>
<h2>贴子列表</h2>
{data.map(item=><PostItem title={item.title} author={item.author} date={item.date}></PostItem>)}
</>
)
}
}
export default PostList
import React, { Component } from 'react'
export class PostItem extends Component {
render() {
// 解构
const {title,author,date} = this.props
return (
<>
<ul>
<li>
<div>{title}</div>
<div>
创建人:<span>{author}</span>
</div>
<div>
创建时间:<span>{date}</span>
</div>
</li>
</ul>
</>
)
}
}
export default PostItem
请注意:使用类样式组件接收父组件传过来的值,用 this.props 就可以直接渲染上去了!!!
3.2、使用函数定义组件,叫函数式组件
import React from "react";
import { Table, Popconfirm, InputNumber } from "antd"; // 函数式组件,在这里接收父组件传过来的值
export default function Tablesss(props) {
return <h2>Hello {props.name}!</h2>;
}
请注意:使用函数式组件接收父组件传过来的值,需要在函数的参数里面用props来接收 !!!
3.3、组件的规范
组件的名称必须首字母大写,react内部会根据这个来判断是组件还是普通的HTML标签
函数组件必须有返回值,表示该组件的 UI 结构;如果不需要渲染任何内容,则返回 null
组件就像 HTML 标签一样可以被渲染到页面中。组件表示的是一段结构内容,对于函数组件来说,渲染的内容是函数的返回值就是对应的内容
使用函数名称作为组件标签名称,可以成对出现也可以自闭合
3.4、有状态组件与无状态组件
3.4.1、有状态组件
它属于一个 class 类
有继承
可以通过this来接收状态和属性
如果你想用react的生命周期,想对一些数据进行增删改查的话就要用到有状态组件
3.4.2、无状态组件
它属于一个函数
没有继承功能
没有生命周期
他的动态数据都是通过父组件传值子组件通过props接收渲染,针对一些简单的逻辑判断等等,用无状态组件
3.4.3、什么时候用有状态组件
在不确定或者确定要用到数据增删改查模块就可以
在需要管理状态,或者需要使用生命周期时再用
3.4.4、注意
大部分建议使用无状态组件,因为如果大量用有状态的组件容易触发生命周期和钩子函数,页面会出面加载慢等问题!!!
四、组件三大核心属性
4.1、state
组件的 state 是组件内部的状态,state的变化最终将反映到组件UI的上。我们在组件的构造方法 constructor 中通过 this.state 定义组件的初始状态,并通过调用 this.setState 方法改变组件状态(也是改变组件状态的唯一方式),进而组件UI也会随之重新渲染。
理解:
state是组件对象最重要的属性, 值是对象(可以包含多个key-value的组合)
组件被称为"状态机", 通过更新组件的state来更新对应的页面显示(重新渲染组件)
组件中render方法中的this为组件实例对象
组件自定义的方法中this为undefined,如何解决?
注意:
组件中render方法中的this为组件实例对象
组件自定义的方法中this为undefined,如何解决?
- 强制绑定this: 通过函数对象的 bind()
- 箭头函数
状态数据,不能直接修改或更新
4.1.1、this绑定
1、在 constructor 中使用 bind() 进行硬绑定
constructor() {
this.handleClick = this.handleClick.bind(this);
}
2、直接在元素上使用 bind() 绑定
<label className={className} onClick={this.handleClick.bind(this)}>
3、ES6 有个很有用的语法糖:Arrow Function(箭头函数)它可以很方便的使 this 直接指向 class SwitchButton
<label className={className} onClick={()=>this.handleClick()}>
4.2、props
props就是属性的简写,是单个值,是在父组件中定义或已经在 state 中的值,并将这些值传递给其子组件。props本身不可变,但可以通过触发state的变化,反过来改变props本身的值。
理解:
每个组件对象都会有props(properties的简写)属性
组件标签的所有属性都保存在props中
作用:
用于接收组件外部的数据
传递数据: 通过给组件标签添加属性
接收数据:函数组件通过 参数 props接收数据,类组件通过 this.props接收数据
特点:
可以给组件传递任意类型的数据
props是只读属性,不能对值进行修改
使用类组件时,如果写了构造函数,应该将props传递给super(),否则无法在构造函数中获取到props,其他的地方是可以拿到的
应用场景:
子组件调用父组件的方法
- 子组件要拿到父组件的属性,需要通过
this.props方法 同样地,如果子组件想要调用父组件的方法,只需父组件把要被调用的方法以属性的方式放在子组件上, 子组件内部便可以通过
“this.props.被调用的方法”这样的方式来获取父组件传过来的方法。
- 子组件要拿到父组件的属性,需要通过
父组件调用子组件的方法
- 在 ReactJS 中有个叫 ref 的属性。这个属性就像给组件起个引用名字一样,子组件被设置为 ref 之后(比如 ref=“xxx”)。父组件便可以通过
this.refs.xxx来获取到子组件了。
- 在 ReactJS 中有个叫 ref 的属性。这个属性就像给组件起个引用名字一样,子组件被设置为 ref 之后(比如 ref=“xxx”)。父组件便可以通过
栗子:React 三大属性之一 props的一些简单理解 - 腾讯云开发者社区-腾讯云 (tencent.com)
编码操作:
- 内部读取某个属性值
- this.props.name
- 扩展属性: 将对象的所有属性通过props传递
<Person {...person}/>
- 默认属性值:
Person.defaultProps = {
age: 18,
sex:'男'
}
- 组件类的构造函数
constructor(props){
super(props)
console.log(props)//打印所有属性
}
4.3、refs与事件处理
Refs 是一个 获取 DOM节点或 React元素实例的工具。在 React 中 Refs 提供了一种方式,允许用户访问DOM 节点或者在render方法中创建的React元素
使用情景:
对DOM 元素焦点的控制、内容选择或者媒体播放;
通过对DOM元素控制,触发动画特效;
通第三方DOM库的集成。
编码:
字符串形式的ref(不推荐使用,已过时,存在效率问题)
<input ref="input1"/>
回调形式的ref
<input ref={(c)=>{this.input1 = c}}
<script type="text/babel">
//创建组件
class Demo extends React.Component{
//展示左侧输入框的数据
showData = ()=>{
const {input1} = this
alert(input1.value)
}
//展示右侧输入框的数据
showData2 = ()=>{
const {input2} = this
alert(input2.value)
}
render(){
return(
<div>
<input ref={c => this.input1 = c } type="text" placeholder="点击按钮提示数据"/>
<button onClick={this.showData}>点我提示左侧的数据</button>
<input onBlur={this.showData2} ref={c => this.input2 = c } type="text" placeholder="失去焦点提示数据"/>
</div>
)
}
}
//渲染组件到页面
ReactDOM.render(<Demo a="1" b="2"/>,document.getElementById('test'))
</script>
createRef创建ref容器
myRef = React.createRef()
<input ref={this.myRef}/>
事件处理:
通过onXxx属性指定事件处理函数(注意大小写)
React使用的是自定义(合成)事件, 而不是使用的原生DOM事件
React中的事件是通过事件委托方式处理的(委托给组件最外层的元素)
通过event.target得到发生事件的DOM元素对象
五、组件的属性校验和默认属性
5.1、特殊属性——propTypes
对 Component 设置 propTypes 属性,可以为 Component 的 props 属性进行类型检查
import React, { Component } from 'react'
import Hi,{ Message } from './Hi'
import Person from './person';
export default class HiBox extends Component {
render() {
let age= 19;
return (
<div>
<Hi age={age} hobby={['阅读','运动','听音乐',1,2,3]} onVote={()=>alert("你好,大美女!")} sex="女" info={new Message()} height={180} mobile={13454367654} name="tao"></Hi>
</div>
)
}
}
Hi 子组件:
import React, { Component } from 'react'
import PropTypes from 'prop-types'
class Hi extends Component {
render() {
return (
<div>
<h2 onClick={this.props.onVote} style={{cursor: "pointer"}}>
Hi,我的姓名为:{this.props.name}
<p>我的年龄为:{this.props.age}岁;</p>
<p>爱好为:{this.props.hobby.join("、")}</p>
<p>性别为:{this.props.sex}</p>
<p>身高为:{this.props.height}</p>
<p>手机号为:{this.props.mobile}</p>
</h2>
</div>
)
}
}
// 定义类型 Message
export function Message(){
this.show = ()=>{
alert("你好!");
}
}
// 设置组件Hi的属性
Hi.propTypes = {
// 约束age属性为number类型
age: PropTypes.number,
// 约束hobby属性为数组类型
hobby: PropTypes.array,
// 约束hobby属性必须为number类型的数组
// hobby: PropTypes.arrayOf(PropTypes.number),
// 约束onVote属性必须是一个函数
onVote: PropTypes.func,
// 限制性别必须为男或女,只能是数组中的某一项
sex: PropTypes.oneOf(["男","女"]),
// info属性的值必须是Message类型
// info: PropTypes.instanceOf(Message),
// info可以是number类型,string或者Message类型
info: PropTypes.oneOfType([
PropTypes.number,
PropTypes.string,
PropTypes.instanceOf(Message),
]),
// 约束身高必须在179到220之间
height: function(props,propsName,ComponentName){
// 取出属性值
let value = props[propsName];
if (value<170 || value>220) {
throw new Error("身高必须在179到220之间")
}
},
// 约束手机号必须是以1开头的11位数字
mobile: function (props,propsName,ComponentName){
let value = props[propsName];
if (value) {
if (!/^1\d{10}$/.test(value)) {
throw new Error("手机号必须是以1开头的11位数字")
}
}
},
// name属性必须为string类型而且必须要填写
name:PropTypes.string.isRequired,
}
export default Hi;
运行结果:

5.2、限制单个子元素
使用 PropTypes.element 你可以指定只有一个子元素可以被传递给组件。
import React, { Component } from 'react'
import PropTypes from 'prop-types'
export default class Person extends Component {
render() {
return (
<div>person</div>
)
}
}
Person.propTypes = {
// 限制子元素必须为number类型,而且必填
// children: PropTypes.number.isRequired,
// 限制子元素只能为单个元素
children: PropTypes.element.isRequired
}
<Person>
<span>{19}</span>
</Person>
5.3、默认标签属性值
当组件引用的时候,没有传入该sex和age属性时,会使用默认值。
//指定默认标签属性值
Person.defaultProps = {
sex:'男',//sex默认值为男
age:18 //age默认值为18
}
六、生命周期
其实React组件并不是真正的DOM, 而是会生成JS对象的虚拟DOM,虚拟DOM会经历创建,更新,删除的过程
这一个完整的过程就构成了组件的生命周期,React 提供了钩子函数让我们可以在组件生命周期的不同阶段添加操作
6.1、理解
组件从创建到死亡它会经历一些特定的阶段。
React组件中包含一系列勾子函数(生命周期回调函数), 会在特定的时刻调用。
我们在定义组件时,会在特定的生命周期回调函数中,做特定的工作。
6.2、生命周期流程图

解析:

6.3、react的生命周期大概分为
组件装载(Mount)组件第一次渲染到Dom树
组件更新(update)组件state,props变化引发的重新渲染
组件卸载(Unmount)组件从Dom树删除
6.4、生命周期的三个阶段
1. 初始化阶段: 由ReactDOM.render()触发---初次渲染
- constructor():在此初始化state,绑定成员函数this环境,props本地化,constructor 构造函数只在初始化化的时候执行一次
- getDerivedStateFromProps():在创建时或更新时的render之前执行,让
props能更新到组件内部state中,必须是静态的。它应返回一个对象来更新 state,如果返回null则不更新任何内容。 - render():
渲染函数,唯一的一定不能省略的函数,必须有返回值,返回null或false表示不渲染任何DOM元素。它是一个仅仅用于渲染的纯函数,返回值完全取决于this.state和this.props,不能在函数中任何修改props、state、拉取数据等具有副作用的操作。render函数返回的是JSX的对象,该函数并不因为这渲染到DOM树,何时进行真正的渲染是有React库决定的。 - componentDidMount():
挂载成功函数。该函数不会再render函数调用完成之后立即调用,因为render函数仅仅是返回了JSX的对象,并没有立即挂载到DOM树上,而componentDidMount是在组件被渲染到DOM树之后被调用的。另外,componentDidMount函数在进行服务器端渲染时不会被调用。
2. 更新阶段: 由组件内部this.setSate()或父组件重新render触发
- getDerivedStateFromProps()
- shouldComponentUpdate()
- render()
- getSnapshotBeforeUpdate()
- componentDidUpdate()
3. 卸载组件: 由ReactDOM.unmountComponentAtNode()触发
- componentWillUnmount()
6.5、重要的勾子函数
render:初始化渲染或更新渲染调用
componentDidMount:开启监听, 发送ajax请求
componentWillUnmount:做一些收尾工作, 如: 清理定时器
6.6、即将废弃的勾子
componentWillMount
componentWillReceiveProps
componentWillUpdate
现在使用会出现警告,下一个大版本需要加上UNSAFE_前缀才能使用,以后可能会被彻底废弃,不建议使用。
6.7、示例说明
6.7.1、组件装载(Mount)
import React, { Component } from "react";
class Hi extends Component {
constructor(props) {
super(props);
console.log("constructor()函数被调用,构造函数");
this.state = {
n: 100,
};
}
render() {
console.log("render()函数被调用,返回UI描述");
return <h2>Hello {this.props.name}!</h2>;
}
static getDerivedStateFromProps() {
console.log(
"getDerivedStateFromProps()函数被调用,让 props 能更新到组件内部 state中"
);
return null;
}
componentDidMount() {
console.log("componentDidMount()函数被调用,组件被挂载到DOM后");
}
}
export default Hi;
运行结果:

6.7.1.1、构造方法 constructor
说明:
如果不需要初始化state,或者不进行方法的绑定,则不需要实现constructor构造函数
在组件挂载前调用构造函数,如果继承
React.Component,则必须调用super(props)constructor通常用于处理了state初始化和为事件处理函数绑定
this实例尽量避免将props外部数据赋值给组件内部state状态
注意:constructor 构造函数只在初始化化的时候执行一次
栗子:
import React, { Component } from "react";
class Counter extends Component {
constructor(props) {
super(props);
this.state = {
count: 0,
};
//解决changeWeather中this指向问题
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
console.log(this);
this.setState({ count: this.state.count + 1 });
}
render() {
return (
<div>
<h2>计算器</h2>
<button onClick={this.handleClick}>点击加1</button>
<span> {this.state.count} </span>
</div>
);
}
}
export default Counter;
运行结果:

组件 state 也可以不定义在constructor构造函数中,事件函数也可以通过箭头函数处理 this 问题
因此如果不想使用 constructor 也可以将两者移出
import React, { Component } from "react";
class Counter extends Component {
//初始化组件状态
state = {
count: 0,
};
//箭头函数处理this问题,自定义方法——要用赋值语句的形式+箭头函数
handleClick = () => {
console.log(this);
this.setState(() => ({ count: this.state.count + 1 }));
};
render() {
return (
<div>
<h2>计算器</h2>
<button onClick={this.handleClick}>点击加1</button>
<span> {this.state.count} </span>
</div>
);
}
}
export default Counter;
箭头函数中的this指向了当前组件实例,而普通函数则指向undefined。箭头函数内this是词法作用域,由上下文确定。
6.7.1.2、构造方法 constructor
6.7.2、组件更新(update)
6.7.3、组件卸载(Unmount)
React 的学习笔记一 (未完结)的更多相关文章
- React 入门学习笔记整理目录
React 入门学习笔记整理(一)--搭建环境 React 入门学习笔记整理(二)-- JSX简介与语法 React 入门学习笔记整理(三)-- 组件 React 入门学习笔记整理(四)-- 事件 R ...
- The Road to learn React书籍学习笔记(第二章)
The Road to learn React书籍学习笔记(第二章) 组件的内部状态 组件的内部状态也称为局部状态,允许保存.修改和删除在组件内部的属性,使用ES6类组件可以在构造函数中初始化组件的状 ...
- The Road to learn React书籍学习笔记(第三章)
The Road to learn React书籍学习笔记(第三章) 代码详情 声明周期方法 通过之前的学习,可以了解到ES6 类组件中的生命周期方法 constructor() 和 render() ...
- React Native 学习笔记--进阶(二)--动画
React Native 进阶(二)–动画 动画 流畅.有意义的动画对于移动应用用户体验来说是非常必要的.我们可以联合使用两个互补的系统:用于全局的布局动画LayoutAnimation,和用于创建更 ...
- [Firefly引擎][学习笔记三][已完结]所需模块封装
原地址:http://www.9miao.com/question-15-54671.html 学习笔记一传送门学习笔记二传送门 学习笔记三导读: 笔记三主要就是各个模块的封装了,这里贴 ...
- [Firefly引擎][学习笔记二][已完结]卡牌游戏开发模型的设计
源地址:http://bbs.9miao.com/thread-44603-1-1.html 在此补充一下Socket的验证机制:socket登陆验证.会采用session会话超时的机制做心跳接口验证 ...
- [Firefly引擎][学习笔记四][已完结]服务器端与客户端的通讯
原地址:http://www.9miao.com/question-15-54981.html 传送门:学习笔记一学习笔记二学习笔记三 前言:学习笔记三是模块封装,这个在持续开发中会不断更新, 因为写 ...
- React+Redux学习笔记:React+Redux简易开发步骤
前言 React+Redux 分为两部分: UI组件:即React组件,也叫用户自定义UI组件,用于渲染DOM 容器组件:即Redux逻辑,处理数据和业务逻辑,支持所有Redux API,参考之前的文 ...
- [Firefly引擎][学习笔记一][已完结]带用户验证的聊天室
原地址:http://bbs.9miao.com/thread-44571-1-1.html 前言:早在群里看到大鸡蛋分享他们团队的Firefly引擎,但一直没有时间去仔细看看,恰好最近需要开发一个棋 ...
- React Redux学习笔记
React Router React Router 使用教程 Redux中间件middleware [译]深入浅出Redux中间件 Redux学习之一:何为middleware? ES6 ES6新特性 ...
随机推荐
- 题解 [HDU6746] Civilization(贪心+模拟)
来源:2020 年百度之星·程序设计大赛 - 初赛一 一道贪心 + 细节模拟题 题意很简单,这里不详细写了 观察题目,\(n\) 只有 500 ,可以 \(n \times n\) 枚举每个位置作为起 ...
- 0x62 图论-最小生成树
A题:走廊泼水节 链接:https://ac.nowcoder.com/acm/contest/1056/A 题目描述 给定一棵N个节点的树,要求增加若干条边,把这棵树扩充为完全图,并满足图的唯一最小 ...
- ElementUI - <el-table> 表格 selection 设置的复选框禁止选中某些行
https://blog.csdn.net/weixin_44198965/article/details/119026054
- python · SQL | MySQL 配置与 python 连接数据库
来存档一下搞 sql 的过程,方便以后查阅. 安装与配置 mysql server:https://blog.csdn.net/zhende_lan/article/details/129318514 ...
- React报错之ref返回undefined或null
正文从这开始~ 总览 当我们试图在其对应的DOM元素被渲染之前访问其current属性时,React的ref通常会返回undefined或者null.为了解决该问题,可以在useEffect钩子中访问 ...
- LaTeX 公式识别问题
问题 想要方便的图片公式识别工具来写Latex(论文)/markdown(笔记)文件 工具推荐 1.mathpix 识别成功率最高(无论是多行,表格表现都非常良好),最好用的工具,但是收费高且付费麻烦 ...
- 例2.8 已知带头结点单链表L,设计算法实现:以表中第一元素作为标准,将表中所有值小于第一个元素的结点均放在第一结点之前,所有值大于第一元素的结点均放在第一元素结点之后。
1.题目 例2.8已知带头结点单链表L,设计算法实现:以表中第一元素作为标准,将表中所有值小于第一个元素的结点均放在第一结点之前,所有值大于第一元素的结点均放在第一元素结点之后. 2.算法分析 3.代 ...
- 【KEIL】User's Guide
µVision User's Guide
- [转帖]「开源摘星计划」Prometheus监控Harbor(二进制版)
推荐 原创 键客李大白2022-08-08 11:35:07博主文章分类:Harbor进阶实战(企业实战)著作权 文章标签云原生运维Harbor文章分类kubernetes云计算私藏项目实操分享阅读数 ...
- [转帖]PostgreSQL数据加载工具之pg_bulkload
https://www.jianshu.com/p/b576207f2f3c 1. pg_bulkload介绍 PostgreSQL提供了一个copy命令的便利数据加载工具,copy命令源于Postg ...