【09】基础知识:React组件的生命周期
组件从创建到死亡它会经历一些特定的阶段。
React 组件中包含一系列勾子函数(生命周期回调函数 <=> 生命周期钩子函数 <=> 生命周期函数 <=> 生命周期钩子),会在特定的时刻调用。
我们在定义组件时,会在特定的生命周期回调函数中,做特定的工作。
一、react 生命周期旧

初始化阶段:由 ReactDOM.render() 触发,初次渲染
1、构造器:constructor()
2、组件将要挂载的钩子:componentWillMount()
3、组件渲染或组件更新的钩子:render()
4、 组件挂载完毕的钩子:componentDidMount()
更新阶段:由组件内部 this.setSate() / this.forceUpdate() 或父组件 render 触发
1、控制组件更新的 “阀门” :shouldComponentUpdate()
2、组件将要更新的钩子:componentWillUpdate()
3、组件渲染或组件更新的钩子:render()
4、组件更新完毕的钩子:componentDidUpdate()
卸载组件:由 ReactDOM.unmountComponentAtNode() 触发
1、组件将要卸载的钩子:componentWillUnmount()
父组件 render:组件 props 值改变触发
1、组件将要接收新的 props 的钩子:componentWillReceiveProps()
二、react 生命周期新

初始化阶段:由 ReactDOM.render() 触发,初次渲染
1、构造器:constructor()
2、从 props 得到一个派生状态:static getDerivedStateFromProps()
3、组件渲染或组件更新的钩子:render()
4、 组件挂载完毕的钩子:componentDidMount()
更新阶段:由组件内部 this.setSate() / this.forceUpdate() 或父组件 render 触发
1、static getDerivedStateFromProps()
2、控制组件更新的 “阀门” :shouldComponentUpdate()
3、组件渲染或组件更新的钩子:render()
4、在更新之前获取快照:getSnapshotBeforeUpdate()
5、组件更新完毕的钩子:componentDidUpdate()
卸载组件:由 ReactDOM.unmountComponentAtNode() 触发
1、组件将要卸载的钩子:componentWillUnmount()
三、新旧生命周期总结
重要的勾子
1、组件渲染或组件更新的钩子:render()
2、组件挂载完毕的钩子:componentDidMount()
一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息
3、组件将要卸载的钩子:componentWillUnmount()
一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息
即将废弃的勾子
现在使用会出现警告,下一个大版本需要加上 UNSAFE_ 前缀才能使用,以后可能会被彻底废弃,不建议使用。
1、组件将要挂载的钩子:componentWillMount()
2、组件将要接收新的 props 的钩子:componentWillReceiveProps()
3、组件将要更新的钩子:componentWillUpdate()
四、案例
案例1:引出生命周期
需求:定义组件实现以下功能:
1、让指定的文本做显示 / 隐藏的渐变动画
2、从完全可见,到彻底消失,耗时 2S
3、点击 “不活了” 按钮从界面中卸载组件
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>1_引出生命周期</title>
</head>
<body><!-- 准备好一个“容器” --><div id="test"></div><!-- 引入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">// 创建组件class Life extends React.Component {state = { opacity: 1 }death = () => {// clearInterval(this.timer) // 清除定时器(可以卸载componentWillUnmount中)ReactDOM.unmountComponentAtNode(document.getElementById('test')) // 卸载组件}// 组件挂载完毕的钩子componentDidMount() {console.log('componentDidMount')this.timer = setInterval(() => {let { opacity } = this.state // 获取原状态opacity -= 0.1 // 减小0.1if (opacity <= 0) opacity = 1 this.setState({ opacity }) // 设置新的透明度}, 200)}// 组件将要卸载的钩子componentWillUnmount() {console.log('componentWillUnmount')clearInterval(this.timer) // 清除定时器}// 初始化渲染、状态更新之后 (state变化会触发render函数,定时器如果写在render中,会造成无限递归)render() {console.log('render')return (<div><h2 style={{ opacity: this.state.opacity }}>React学不会怎么办?</h2><button onClick={this.death}>不活了</button></div>)}}// 渲染组件ReactDOM.render(<Life />, document.getElementById('test'))</script>
</body>
</html>
案例二:React 生命周期旧
累加器,点击数值+1
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>2_react生命周期(旧)</title>
</head>
<body><!-- 准备好一个“容器” --><div id="test"></div><!-- 引入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">// 创建组件class Count extends React.Component {// 构造器constructor(props) {console.log('Count---constructor')super(props)this.state = { count: 0 } // 初始化状态}// 加1按钮的回调add = () => {const { count } = this.statethis.setState({ count: count+1 }) // 更新状态}// 卸载组件按钮的回调death = () => {ReactDOM.unmountComponentAtNode(document.getElementById('test'))}// 强制更新按钮的回调force = () => {this.forceUpdate()}// 组件将要挂载的钩子componentWillMount() {console.log('Count---componentWillMount')}// 控制组件更新的 “阀门” shouldComponentUpdate() {console.log('Count---shouldComponentUpdate')// 不写时,默认值为true,代表允许组件更新;写了以后,必须有返回值Boolan,true/falsereturn true}// 组件将要更新的钩子componentWillUpdate() {console.log('Count---componentWillUpdate')}// 组件渲染或组件更新的钩子render() {console.log('Count---render')const { count } = this.statereturn (<div><h2>当前求和为:{ count }</h2><button onClick={this.add}>点我+1</button><button onClick={this.death}>卸载组件</button><button onClick={this.force}>不更改任何状态中的数据,强制更新一下</button></div>)}// 组件挂载完毕的钩子componentDidMount() {console.log('Count---componentDidMount')}// 组件更新完毕的钩子componentDidUpdate() {console.log('Count---componentDidUpdate')}// 组件将要卸载的钩子componentWillUnmount() {console.log('Count---componentWillUnmount')}}// 渲染组件ReactDOM.render(<Count />, document.getElementById('test'))</script>
</body>
</html>
父组件 render 触发子组件 props 值改变
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>2_react生命周期(旧)</title>
</head>
<body><!-- 准备好一个“容器” --><div id="car"></div><!-- 引入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">// 父组件class A extends React.Component {// 初始化状态state = { carName: '奔驰' }changeCar = () => {this.setState({ carName: '奥拓' })}render() {return (<div><div>我是A组件</div><button onClick={this.changeCar}>换车</button><B carName={this.state.carName}/></div>)}}// 子组件class B extends React.Component {// 组件将要接收新的props的钩子(props第一次接收值时不触发)componentWillReceiveProps(props) {console.log('B---componentWillReceiveProps', props)}// 控制组件更新的 “阀门” shouldComponentUpdate() {console.log('B---shouldComponentUpdate')// 不写时,默认值为true,代表允许组件更新;写了以后,必须有返回值Boolan,true/falsereturn true}// 组件将要更新的钩子componentWillUpdate() {console.log('B---componentWillUpdate')}// 组件渲染或组件更新的钩子render() {console.log('B---render')const { carName } = this.propsreturn (<div>我是B组件,接收到的车是:{carName}</div>)}// 组件更新完毕的钩子componentDidUpdate() {console.log('Count---componentDidUpdate')}}// 渲染组件ReactDOM.render(<A />, document.getElementById('car'))</script>
</body>
</html>
案例三:React 生命周期新
新生命周期新增方法:
static getDerivedStateFromProps() 从props得到一个派生状态,此方法适用于罕见的用例,即 state 的值在任何时候都取决于 props 。派生状态会导致代码冗余。
getSnapshotBeforeUpdate() 在更新之前获取快照,此用法并不常见。它使得组件能在发生改变之前从 DOM 中捕获一些信息(例如,滚动位置)。此生命周期的任何返回值将作为参数传递给 componentDidUpdate()。
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>3_react生命周期(新)</title>
</head>
<body><!-- 准备好一个“容器” --><div id="test"></div><!-- 引入react核心库 --><script type="text/javascript" src="../js/17.0.1/react.development.js"></script><!-- 引入react-dom,用于支持react操作DOM --><script type="text/javascript" src="../js/17.0.1/react-dom.development.js"></script><!-- 引入babel,用于将jsx转为js --><script type="text/javascript" src="../js/17.0.1/babel.min.js"></script><script type="text/babel">// 创建组件class Count extends React.Component {// 构造器constructor(props) {console.log('Count---constructor')super(props)this.state = { count: 0 } // 初始化状态}// 加1按钮的回调add = () => {const { count } = this.statethis.setState({ count: count+1 }) // 更新状态}// 卸载组件按钮的回调death = () => {ReactDOM.unmountComponentAtNode(document.getElementById('test'))}// 强制更新按钮的回调force = () => {this.forceUpdate()}// 从props得到一个派生状态:若state的值在任何时候都取决于props,那么可以使用getDerivedStateFromPropsstatic getDerivedStateFromProps(props, state) {console.log('getDerivedStateFromProps', props, state)return null // 必须有返回值,状态对象或者null}// 在更新之前获取快照getSnapshotBeforeUpdate() {console.log('getSnapshotBeforeUpdate')return 'atguigu' // 必有有返回值,快照或者null,将作为参数传递给 componentDidUpdate()}// 控制组件更新的 “阀门” shouldComponentUpdate() {console.log('Count---shouldComponentUpdate')// 不写时,默认值为true,代表允许组件更新;写了以后,必须有返回值Boolan,true/falsereturn true}// 组件渲染或组件更新的钩子render() {console.log('Count---render')const { count } = this.statereturn (<div><h2>当前求和为:{ count }</h2><button onClick={this.add}>点我+1</button><button onClick={this.death}>卸载组件</button><button onClick={this.force}>不更改任何状态中的数据,强制更新一下</button></div>)}// 组件挂载完毕的钩子componentDidMount() {console.log('Count---componentDidMount')}// 组件更新完毕的钩子(接收参数:之前的的props、之前的state、传过来的快照)componentDidUpdate(prevProps, prevState, snapshotValue) {console.log('Count---componentDidUpdate', prevProps, prevState, snapshotValue)}// 组件将要卸载的钩子componentWillUnmount() {console.log('Count---componentWillUnmount')}}//渲染组件ReactDOM.render(<Count count={ 199 } />, document.getElementById('test'))</script>
</body>
</html>
案例四:getSnapShotBeforeUpdate 的使用场景
展示新闻列表,1s向上追加一条新闻,并保证页面视图区域内容不变。
思路:
利用 getSnapShotBeforeUpdate() 获取组件更新之前 内容的 scrollHeight,传递给 componentDidUpdate()
组件更新之后,设置当前容器的 scrollTop 值为,当前内容高度 - 组件更新之前内容高度
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>4_getSnapShotBeforeUpdate的使用场景</title><style>.list {width: 200px;height: 150px;background-color: skyblue;overflow: auto;}.news {height: 30px;}</style>
</head>
<body><!-- 准备好一个“容器” --><div id="test"></div><!-- 引入react核心库 --><script type="text/javascript" src="../js/17.0.1/react.development.js"></script><!-- 引入react-dom,用于支持react操作DOM --><script type="text/javascript" src="../js/17.0.1/react-dom.development.js"></script><!-- 引入babel,用于将jsx转为js --><script type="text/javascript" src="../js/17.0.1/babel.min.js"></script><script type="text/babel">class NewsList extends React.Component {state = { newsArr: [] }componentDidMount() {setInterval(() => {const { newsArr } = this.state // 获取原状态const news = '新闻' + (newsArr.length + 1) // 模拟一条新闻this.setState({ newsArr: [news, ...newsArr] }) // 更新状态}, 1000)}getSnapshotBeforeUpdate() {return this.refs.list.scrollHeight}componentDidUpdate(preProps, preState, height) {this.refs.list.scrollTop += this.refs.list.scrollHeight - height}render() {return (<div className="list" ref="list">{this.state.newsArr.map((n, index) => {return <div key={index} className="news">{n}</div>})}</div>)}}ReactDOM.render(<NewsList />, document.getElementById('test'))</script>
</body>
</html>
相关文章:
【09】基础知识:React组件的生命周期
组件从创建到死亡它会经历一些特定的阶段。 React 组件中包含一系列勾子函数(生命周期回调函数 <> 生命周期钩子函数 <> 生命周期函数 <> 生命周期钩子),会在特定的时刻调用。 我们在定义组件时,会在特定的生…...
Pytorch之ConvNeXt图像分类
文章目录 前言一、ConvNeXt设计决策1.设计方案2.Training Techniques3.Macro Design🥇Changing stage compute ratio🥈Change stem to "Patchify" 4.ResNeXt-ify5. Inverted Bottleneck6.Large Kernel Size7.Micro Design✨Replacing ReLU wit…...
Linux系统编程:makefile以及文件系统编程
增量编译概念 首先回顾一下我们之前写的各种gcc指令用来执行程序: 可以看见非常繁琐,两个文件就要写这么多,那要是成百上千岂不完蛋。 所以为了简化工作量,很自然的想到了将这些命令放在一起使用脚本文件来一键执行,…...
《动手学深度学习 Pytorch版》 8.5 循环神经网络的从零开始实现
%matplotlib inline import math import torch from torch import nn from torch.nn import functional as F from d2l import torch as d2lbatch_size, num_steps 32, 35 train_iter, vocab d2l.load_data_time_machine(batch_size, num_steps) # 仍然使用时间机器数据集8.…...
写一个宏,可以将一个整数的二进制位的奇数位和偶数位交换
我们这里是利用按位与来计算的 我们可以想想怎么保留偶数上的位?我们可以利用0x55555555按位与上这个数就保留了偶数 我们知道,16进制0x55555555转换为二进制就是0x01010101010101010101010101010101 我们知道,二进制每一位,如…...
Zabbix监控系统详解2:基于Proxy分布式实现Web应用监控及Zabbix 高可用集群的搭建
文章目录 1. zabbix-proxy的分布式监控的概述1.1 分布式监控的主要作用1.2 监控数据流向1.3 构成组件1.3.1 zabbix-server1.3.2 Database1.3.3 zabbix-proxy1.3.4 zabbix-agent1.3.5 web 界面 2. 部署zabbix代理服务器2.1 前置准备2.2 配置 zabbix 的下载源,安装 za…...
docker 安装oracle
拉取镜像 拉取oracle_11g镜像 拉取oracle镜像(oracle 11.0.2 64bit 企业版 实例名: helowin) Oracle主要在Docker基础上安装,安装环境注意空间和内存,Oracle是一个非常庞大的一个软件, 建议使用网易镜像或阿里镜像网站这里以oracle 11.0.2…...
C++ vector 自定义排序规则(vector<vector<int>>、vector<pair<int,int>>)
vector< int > vector<int> vec{1,2,3,4};//默认从小到大排序 1234 sort(vec.begin(),vec.end()); //从大到小排序 4321 sort(vec.begin(),vec.end(),greater<int>());二维向量vector<vector< int >> vector<vector<int>> vec{{0…...
机器学习 Q-Learning
对马尔可夫奖励的理解 看的这个教程 公式:V(s) R(s) γ * V(s’) V(s) 代表当前状态 s 的价值。 R(s) 代表从状态 s 到下一个状态 s’ 执行某个动作后所获得的即时奖励。 γ 是折扣因子,它表示未来奖励的重要性,通常取值在 0 到 1 之间。…...
产品设计心得体会 优漫动游
产品设计需要综合考虑用户需求、市场需求和技术可行性,从而设计出能够满足用户需求并具有市场竞争力的产品。以下是我在产品设计方面的心得体会: 产品设计心得体会 1.深入了解用户需求:在产品设计之前,需要进行充分的用户调研…...
前端--CSS
文章目录 CSS的介绍 引入方式 代码风格 选择器 复合选择器 (选学) 常用元素属性 背景属性 圆角矩形 Chrome 调试工具 -- 查看 CSS 属性 元素的显示模式 盒模型 弹性布局 一、CSS的介绍 层叠样式表 (Cascading Style Sheets). CSS 能够对网页中元素位置的排版进行像素级精…...
实操指南|如何用 OpenTiny Vue 组件库从 Vue 2 升级到 Vue 3
前言 根据 Vue 官网文档的说明,Vue2 的终止支持时间是 2023 年 12 月 31 日,这意味着从明年开始: Vue2 将不再更新和升级新版本,不再增加新特性,不再修复缺陷 虽然 Vue3 正式版本已经发布快3年了,但据我了…...
系统架构设计:15 论软件架构的生命周期
目录 一 软件架构的生命周期 1 需求分析阶段 2 设计阶段 3 实现阶段 4 构件组装阶段...
金山wps golang面试题总结
简单自我介绍如果多个协程并发写map 会导致什么问题如何解决(sync.map,互斥锁,信号量)chan 什么时候会发生阻塞如果 chan 缓冲区满了是阻塞还是丢弃还是panicchan 什么时候会 panic描述一下 goroutine 的调度机制goroutine 什么时…...
计算机视觉实战--直方图均衡化和自适应直方图均衡化
计算机视觉 文章目录 计算机视觉前言一、直方图均衡化1.得到灰度图2. 直方图统计3. 绘制直方图4. 直方图均衡化 二、自适应直方图均衡化1.自适应直方图均衡化(AHE)2.限制对比度自适应直方图均衡化(CRHE)3.读取图片4.自适应直方图均…...
501. 二叉搜索树中的众数
501. 二叉搜索树中的众数 # Definition for a binary tree node. # class TreeNode: # def __init__(self, val0, leftNone, rightNone): # self.val val # self.left left # self.right right class Solution:def findMode(self, root: Option…...
【Linux】常用命令
目录 文件解压缩服务器文件互传scprsync 进程资源网络curl发送简单get请求发送 POST 请求发送 JSON 数据保存响应到文件 文件 ls,打印当前目录下所有文件和目录; ls -l,打印每个文件的基本信息 pwd,查看当前目录的路径 查看文件 catless:可以左右滚动阅读more :翻…...
机器人制作开源方案 | 齿轮传动轴偏心轮摇杆简易四足
1. 功能描述 齿轮传动轴偏心轮摇杆简易四足机器人是一种基于齿轮传动和偏心轮摇杆原理的简易四足机器人。它的设计原理通常如下: ① 齿轮传动:通过不同大小的齿轮传动,实现机器人四条腿的运动。通常采用轮式齿轮传动或者行星齿轮传动…...
Windows中将tomcat以服务的形式安装,然后在服务进行启动管理
Windows中将tomcat以服务的形式安装,然后在服务进行启动管理 第一步: 在已经安装好的tomcat的bin目录下: 输入cmd,进入命令窗口 安装服务: 输入如下命令,最后是你的服务名,避免中文和特殊字符 service.…...
解决ERROR: No query specified的错误以及\G 和 \g 的区别
文章目录 1. 复现错误2. 分析错误3. 解决问题4. \G和\g的区别 1. 复现错误 今天使用powershell连接数据库后,执行如下SQL语句: mysql> select * from student where id 39 \G;虽然成功查询除了数据,但报出如下错误的信息: my…...
微信小程序之bind和catch
这两个呢,都是绑定事件用的,具体使用有些小区别。 官方文档: 事件冒泡处理不同 bind:绑定的事件会向上冒泡,即触发当前组件的事件后,还会继续触发父组件的相同事件。例如,有一个子视图绑定了b…...
8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...
springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...
接口自动化测试:HttpRunner基础
相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具,支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议,涵盖接口测试、性能测试、数字体验监测等测试类型…...
数学建模-滑翔伞伞翼面积的设计,运动状态计算和优化 !
我们考虑滑翔伞的伞翼面积设计问题以及运动状态描述。滑翔伞的性能主要取决于伞翼面积、气动特性以及飞行员的重量。我们的目标是建立数学模型来描述滑翔伞的运动状态,并优化伞翼面积的设计。 一、问题分析 滑翔伞在飞行过程中受到重力、升力和阻力的作用。升力和阻力与伞翼面…...
rknn toolkit2搭建和推理
安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 ,不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源(最常用) conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...
spring Security对RBAC及其ABAC的支持使用
RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型,它将权限分配给角色,再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...
【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
LangChain 中的文档加载器(Loader)与文本切分器(Splitter)详解《二》
🧠 LangChain 中 TextSplitter 的使用详解:从基础到进阶(附代码) 一、前言 在处理大规模文本数据时,特别是在构建知识库或进行大模型训练与推理时,文本切分(Text Splitting) 是一个…...
