【react】生命周期

news2025/1/1 22:33:06

组件从创建到死亡会经历一些特定的阶段
React组件中包含一系列勾子函数(生命周期回调函数)会在特定的时候调用
我们 在定义组件时,会在特定的生命周期回调函数中做特定的工作

一、旧版本的生命周期

在这里插入图片描述

1、初始化阶段

  1. constructor()
  2. componentWillMount()
  3. render()
  4. componentDidMount()
    一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息
<script type="text/babel">
	class Count extends React.Component{

		//构造器
		constructor(props){
			console.log('Count---constructor');
			super(props)
			//初始化状态
			this.state = {count:0}
		}

		//组件将要挂载的钩子
		componentWillMount(){
			console.log('Count---componentWillMount');
		}

		//组件挂载完毕的钩子
		componentDidMount(){
			console.log('Count---componentDidMount');
		}

		render(){
			console.log('Count---render');
			const {count} = this.state
			return(
				<div>
					<h2>当前求和为:{count}</h2>
				</div>
			)
		}
	}
	ReactDOM.render(<Count/>,document.getElementById('test'))
</script>

执行的顺序如下:

在这里插入图片描述

2、更新阶段

更新阶段有三条路线如下:

(1)调用setState()更新状态----shouldComponentUpdate----componentWillUpdate----render----componentDidUpdate

shouldComponentUpdate组件是否应该被更新,控制组件更新的“阀门”。如果在组件中没有写shouldComponentUpdate勾子,默认返回的是true,如果写了就要返回一个布尔值,如果返回true则能往下走,false不能再往下走。

<script type="text/babel">
	class Count extends React.Component{

		//构造器
		constructor(props){
			super(props)
			//初始化状态
			this.state = {count:0}
		}
		
		//加1按钮的回调
		add = ()=>{
			//获取原状态
			const {count} = this.state
			//更新状态
			this.setState({count:count+1})
		}

		//控制组件更新的“阀门”
		shouldComponentUpdate(){
			console.log('Count---shouldComponentUpdate');
			return true
		}
		
		//组件将要更新的钩子
		componentWillUpdate(){
			console.log('Count---componentWillUpdate');
		}

		//组件更新完毕的钩子
		componentDidUpdate(){
			console.log('Count---componentDidUpdate');
		}

		render(){
			const {count} = this.state
			return(
				<div>
					<h2>当前求和为:{count}</h2>
					<button onClick={this.add}>点我+1</button>
				</div>
			)
		}
	}
	ReactDOM.render(<Count/>,document.getElementById('test'))
</script>

执行的顺序如下:

在这里插入图片描述

注意:每触发一次setState就会调用一次shouldComponentUpdate,如果在组件中写了shouldComponentUpdate没有返回布尔值就会报错。

在这里插入图片描述

(2)调用forceUpdate()强制更新----componentWillUpdate----render----componentDidUpdate

不对状态做出更改,组件也能更新,不受shouldComponentUpdate阀门的控制

<script type="text/babel">
	class Count extends React.Component{

		//构造器
		constructor(props){
			super(props)
			//初始化状态
			this.state = {count:0}
		}
		
		//强制更新按钮的回调
		force = ()=>{
			this.forceUpdate()
		}
		
		//组件将要更新的钩子
		componentWillUpdate(){
			console.log('Count---componentWillUpdate');
		}

		//组件更新完毕的钩子
		componentDidUpdate(){
			console.log('Count---componentDidUpdate');
		}

		render(){
			const {count} = this.state
			return(
				<div>
					<h2>当前求和为:{count}</h2>
					<button onClick={this.force}>不更改任何状态中的数据,强制更新一下</button>
				</div>
			)
		}
	}
	ReactDOM.render(<Count/>,document.getElementById('test'))
</script>

执行的顺序如下:

在这里插入图片描述

(3)父组件render----componentWillReceiveProps----shouldComponentUpdate----componentWillUpdate----render----componentDidUpdate

例:有A,B两个组件,A组件维护状态,但是A组件不展示,展示到B组件,形成父子关系

<script type="text/babel">
	//父组件A
	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>
			)
		}
	}
	//子组件B
	class B extends React.Component{
		//组件将要接收新的props的钩子
		componentWillReceiveProps(props){
			console.log('B---componentWillReceiveProps',props);
		}

		//控制组件更新的“阀门”
		shouldComponentUpdate(){
			console.log('B---shouldComponentUpdate');
			return true
		}
		//组件将要更新的钩子
		componentWillUpdate(){
			console.log('B---componentWillUpdate');
		}

		//组件更新完毕的钩子
		componentDidUpdate(){
			console.log('B---componentDidUpdate');
		}

		render(){
			console.log('B---render');
			return(
				<div>我是B组件,接收到的车是:{this.props.carName}</div>
			)
		}
	}
	ReactDOM.render(<A/>,document.getElementById('test'))
</script>

父组件render,子组件响应componentWillReceiveProps勾子(组件将要接收参数)

注意:父组件第一次render不会调用componentWillReceiveProps,要修改完状态后父组件重新render才会调用

执行的顺序如下:

在这里插入图片描述

3、卸载组件

componentWillUnmount
一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息

<script type="text/babel">
	class Count extends React.Component{

		//构造器
		constructor(props){
			super(props)
			//初始化状态
			this.state = {count:0}
		}

		//卸载组件按钮的回调
		death = ()=>{
			ReactDOM.unmountComponentAtNode(document.getElementById('test'))
		}

		//组件将要卸载的钩子
		componentWillUnmount(){
			console.log('Count---componentWillUnmount');
		}

		render(){
			console.log('Count---render');
			const {count} = this.state
			return(
				<div>
					<h2>当前求和为:{count}</h2>
					<button onClick={this.death}>卸载组件</button>
				</div>
			)
		}
	}
	ReactDOM.render(<Count/>,document.getElementById('test'))
</script>

二、新版本的生命周期

新版本的生命周期和旧版本的相比,即将废弃三个勾子:componentWillMountcomponentWillUpdatecomponentWillReceiveProps
同时提出了两个新的勾子:getDerivedStateFromPropsgetSnapshotBeforeUpdate,剩下的跟旧版本的相同。

注意:如果在新版本的react中使用即将废弃的旧版本中的三个生命周期勾子,目前能够正常显示但是会报警告,后期不排除不能用直接报错
如果实在要用,需要使用别名UNSAFE_componentWillMountUNSAFE_componentWillUpdateUNSAFE_componentWillReceiveProps

官网描述 https://react.docschina.org/blog/2018/03/27/update-on-async-rendering.html

在这里插入图片描述

1、初始化阶段

  1. constructor()
  2. getDerivedStateFromProps()
  3. render()
  4. componentDidMount()
<script type="text/babel">
	class Count extends React.Component{

		//构造器
		constructor(props){
			super(props)
			//初始化状态
			this.state = {count:0}
		}

		//若state的值在任何时候都取决于props,那么可以使用getDerivedStateFromProps
		static getDerivedStateFromProps(props,state){
			console.log('Count---getDerivedStateFromProps',props,state);
			return null
		}
		
		//组件挂载完毕的钩子
		componentDidMount(){
			console.log('Count---componentDidMount');
		}

		render(){
			console.log('Count---render');
			const {count} = this.state
			return(
				<div>
					<h2>当前求和为:{count}</h2>
					<button onClick={this.death}>卸载组件</button>
				</div>
			)
		}
	}
	ReactDOM.render(<Count count={199}/>,document.getElementById('test'))
</script>

组件挂载和更新都会触发getDerivedStateFromProps

执行的顺序如下:

在这里插入图片描述

注意: getDerivedStateFromProps()要放在类上而不是实例上,要加上static,否则会报错如下:

在这里插入图片描述

要有返回值,并且值为null或者一个对象,否则会报错如下:

在这里插入图片描述

如果返回的是null,则页面上展示的状态值是constructor中的,并且更改值的操作不会受影响;如果返回的是接到的props或者其他对象,则页面上展示的是props中的值或者自己写死的值,并且无法触发其他更改值的操作。

官网详细描述:https://zh-hans.reactjs.org/docs/react-component.html#static-getderivedstatefromprops

2、更新阶段

  1. getDerivedStateFromProps
  2. shouldComponentUpdate()
  3. render()
  4. getSnapshotBeforeUpdate
  5. componentDidUpdate()
<script type="text/babel">
	class Count extends React.Component{

		//构造器
		constructor(props){
			super(props)
			//初始化状态
			this.state = {count:0}
		}
		
		//加1按钮的回调
		add = ()=>{
			//获取原状态
			const {count} = this.state
			//更新状态
			this.setState({count:count+1})
		}

		//若state的值在任何时候都取决于props,那么可以使用getDerivedStateFromProps
		static getDerivedStateFromProps(props,state){
			console.log('Count---getDerivedStateFromProps',props,state);
			return null
		}

		//在更新之前获取快照
		getSnapshotBeforeUpdate(){
			console.log('Count---getSnapshotBeforeUpdate');
			return '888'
		}
		
		//控制组件更新的“阀门”
		shouldComponentUpdate(){
			console.log('Count---shouldComponentUpdate');
			return true
		}
		
		//组件更新完毕的钩子
		componentDidUpdate(preProps,preState,snapshotValue){
			console.log('Count---componentDidUpdate',preProps,preState,snapshotValue);
		}

		render(){
			console.log('Count---render');
			const {count} = this.state
			return(
				<div>
					<h2>当前求和为:{count}</h2>
					<button onClick={this.add}>点我+1</button>
					<button onClick={this.death}>卸载组件</button>
				</div>
			)
		}
	}
	ReactDOM.render(<Count count={199}/>,document.getElementById('test'))
</script>

执行的顺序如下:

在这里插入图片描述

如果组件执行完了componentDidUpdate意味着组件完成更新了,页面上已经出现了更新之后的效果,之前那些东西就获取不到了,利用getSnapshotBeforeUpdate快照就可以在更新之前获取信息。

官网详细描述:https://zh-hans.reactjs.org/docs/react-component.html#getsnapshotbeforeupdate

例:getSnapShotBeforeUpdate的使用场景

<div id="test"></div>
.list{
	width: 200px;
	height: 150px;
	background-color: skyblue;
	overflow: auto;
}
.news{
	height: 30px;
}
<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>

3、卸载组件

1、componentWillUnmount()

由ReactDOM.unmountComponentAtNode()触发,与旧版本生命周期相同。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/95268.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CVE-2022-22965:spring参数绑定漏洞

CVE-2022-22965 博客链接&#xff1a;https://www.blog.23day.site/articles/73 漏洞说明 Spring framework 是Spring 里面的一个基础开源框架&#xff0c;其目的是用于简化 Java 企业级应用的开发难度和开发周期,2022年3月31日&#xff0c;VMware Tanzu发布漏洞报告&#xff…

LabVIEW创建自定义书签管理器

LabVIEW创建自定义书签管理器 书签是一种特殊的标记机制&#xff0c;可以添加到VI框图中。任何以井号标签&#xff08;#&#xff09;开头的文本都将被LabVIEW自动识别为书签。这些可用于标记代码不同部分中的待办事项或未完成的任务。当您将主题标签添加框图注释时&#xff0c…

基于java的贪吃蛇游戏-计算机毕业设计

项目介绍 本游戏采用Java环境和Eclipse开发工具&#xff0c;开发了一个界面美观&#xff0c;操作简单并且功能齐全的贪食蛇游戏&#xff0c;整个游戏分为了10个类&#xff0c;实现了游戏的开始、结束、暂停&#xff0c;通过了本游戏的开发&#xff0c;达到了学习Java及Java GU…

使用新路由器有线/无线桥接旧路由器

问题描述 已有一个无线路由器&#xff0c;但信号不能满足需求&#xff0c;遂购买新路由器对其进行桥接。经过在网上搜索和实践&#xff0c;成功配置&#xff0c;将经验记录成帖。 解决方案 无线桥接 1. 打开新路由器设置界面。&#xff08;根据路由器说明说或者网上搜索对应…

新手学python,如何才能更快升职加薪,迎娶白富美,走上人生巅峰

最近在问答里发现好多咨询怎么学习python&#xff0c;或者学习难不难的问题&#xff0c;这里给大家提几点建议&#xff1a; 了解自己的目标 我开始学编程的时候&#xff0c;连基础的知识都不知道&#xff0c;小白的很&#xff01;记得我开始看教材&#xff0c;就是输入“hello…

Vue系列之使用vue init搭建前端项目

文章の目录一、执行 vue init webpack my-project 注意&#xff08;my-project&#xff09;是自己的项目名写在最后前提执行如下代码 npm install -g vue/cli-init一、执行 vue init webpack my-project 注意&#xff08;my-project&#xff09;是自己的项目名 回车既可&…

【时空融合:遥感图像】

MUSTFN: A spatiotemporal fusion method for multi-scale and multi-sensor remote sensing images based on a convolutional neural network &#xff08;MUSTFN&#xff1a;一种基于卷积神经网络的多尺度多传感器遥感影像时空融合方法&#xff09; &#xff08;第一篇关于…

毕业设计-基于大数据的电影爬取与可视化分析系统-python

目录 前言 课题背景和意义 实现技术思路 实现效果图样例 前言 &#x1f4c5;大四是整个大学期间最忙碌的时光,一边要忙着备考或实习为毕业后面临的就业升学做准备,一边要为毕业设计耗费大量精力。近几年各个学校要求的毕设项目越来越难,有不少课题是研究生级别难度的,对本科…

zabbix——分布式监控系统

目录 zabbix概述 zabbix 是什么 zabbix 监控原理 zabbix常见的五个程序 zabbix端口号 安装 zabbix 5.0 部署 zabbix 服务端 部署 zabbix 客户端 自定义监控内容 在客户端创建自定义 key 在 Web 页面创建自定义监控项模板 zabbix 自动发现与自动注册 zabbix 自动发…

第十四届蓝桥杯集训——if——配套基础示例

第十四届蓝桥杯集训——if——配套基础示例 目录 第十四届蓝桥杯集训——if——配套基础示例 例题1&#xff1a;三角形任意两边之和大于第三边 例题2&#xff1a;判断回文数 例题3&#xff1a;狗的年龄 例题4&#xff1a;帐密登录 例题1&#xff1a;三角形任意两边之和大于…

UOS系统搭建NTP服务

做这题的前提是先把ispsrv的dns配置完善 NTP 安装 ntp&#xff08;使用其他 ntp 软件&#xff0c;以下功能均不得分&#xff09;&#xff1b; 在 AppSrv 和 StorageSrv 上创建 CRON 计划任务&#xff1b; 使用 ntpdate 指令&#xff0c;每隔五分钟进行一次时间同步。 截图实现…

功能胶膜行业发展趋势:政策、需求叠加技术驱动 未来市场发展空间大

OCA光学胶膜、半导体制造用胶膜等均属于功能胶膜。我国功能胶膜行业发展趋势如下&#xff1a; 1、政策陆续出台&#xff0c;将不断夯实功能胶膜行业发展基础 近年来&#xff0c;国家出台了一系列相关政策来推动功能胶膜行业发展与进步&#xff0c;尤其是在2019年&#xff0c;国…

uniCloud云开发之创建创建一个uniapp项目并关联uniCloud

uniCloud云开发之创建创建一个uniapp项目前言1.下载最新版的HBuilderX&#xff0c;并创建一个uniCloud的项目2、关联云服务空间3、会出来需要登录没有登录的去注册一个就好了&#xff0c;然后新建4、这样就关联好云数据库了5、创建云函数6、调用云函数&#xff08;1&#xff09…

十分钟就能上手Prometheus与Grafana监控SpringBoot项目

&#x1f341; 作者&#xff1a;知识浅谈&#xff0c;CSDN签约讲师&#xff0c;CSDN原力作者&#xff0c;后端领域优质创作者&#xff0c;热爱分享创作 &#x1f492; 公众号&#xff1a;知识浅谈 &#x1f4cc; 擅长领域&#xff1a;全栈工程师、爬虫、ACM算法 &#x1f525; …

深度学习——微调笔记+代码

1.微调在深度学习中计算机视觉最重要的技术&#xff0c;微调也是迁移学习 2.标注一个数据集很贵 ①ImageNet标注了1000多万张图片&#xff0c;实际使用120万张图片&#xff0c;类别是1000&#xff0c;大型数据集 ②Fashion-MNIST一共有6万张图片&#xff0c;类别是10&#xf…

matlab:鼠标循环点击器

目录简介使用说明板块1采点板块作用名称解释板块2坐标板块作用名称解释板块3历史数据板块作用名称解释板块4循环点击板块作用名称解释程序附注简介 采集PC端一个或是多个点的位置坐标&#xff0c;对这些位置可以按照次序循环点击。&#xff08;之前玩阴阳师的时候&#xff0c;…

动态规划问题——矩阵的最小路径和

题目&#xff1a; 给定一个矩阵m&#xff0c;从左上角开始每次只能向右或者向下走&#xff0c;最后到达右下角的位置&#xff0c;路径上所有的数字累加起来就是路径和&#xff0c;返回所有路径中最小的路径和。 示例&#xff1a; 给定的m如下&#xff1a; 1 3 …

灌区信息化管理系统解决方案 灌区用水量测系统介绍

平升电子灌区信息化管理系统解决方案/灌区用水量测系统&#xff0c;对灌区的渠道水位、流量、水雨情、土壤墒情、气象等信息进行监测&#xff0c;同时对泵站、闸门进行远程控制&#xff0c;对重点区域进行视频监控&#xff0c;实现了信息的采集、统计、分析、控制等功能&#x…

我国均温板行业发展趋势:5G手机领域需求强劲 今年市场空间或超15亿

均温板&#xff08;VaporChamber&#xff09;技术从原理上类似于热管&#xff0c;但在传导方式上有所区别。热管为一维线性热传导&#xff0c;而真空腔均热板中的热量则是在一个二维的面上传导&#xff0c;因此效率更高。具体来说&#xff0c;真空腔底部的液体在吸收芯片热量后…

【图像去噪】非局部均值(NLM)滤波图像去噪【含Matlab源码 420期】

⛄一、图像去噪及滤波简介 1 图像去噪 1.1 图像噪声定义 噪声是干扰图像视觉效果的重要因素&#xff0c;图像去噪是指减少图像中噪声的过程。噪声分类有三种&#xff1a;加性噪声&#xff0c;乘性噪声和量化噪声。我们用f(x,y&#xff09;表示图像&#xff0c;g(x,y&#xff0…