【react】生命周期

组件从创建到死亡会经历一些特定的阶段
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()触发,与旧版本生命周期相同。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
React生命周期钩子是在组件的不同阶段执行特定的操作的函数。根据引用提供的信息,React组件的生命周期可以分为实例化、存在期和销毁期。在实例化阶段,以下方法会被调用(按顺序执行):getDefaultProps、getInitialState、componentWillMount、render和componentDidMount。 在存在期阶段,组件会根据不同的情况执行不同的生命周期钩子。其中,引用提到的两个生命周期钩子getDerivedStateFromProps和getSnapshotBeforeUpdate属于存在期。 getDerivedStateFromProps是一个静态方法生命周期钩子(引用),它在组件接收新的props时被调用,并且它应该返回一个新的state对象或null值。这个钩子主要用于在props改变时更新组件的state。 getSnapshotBeforeUpdate是另一个存在期的生命周期钩子,它在组件更新之前被调用。它的返回值将作为componentDidUpdate方法的第三个参数传递。这个钩子通常用于在组件更新前保存一些信息,比如滚动位置,然后在组件更新后恢复滚动位置。 除了上述提到的钩子外,React还提供了其他的生命周期钩子函数,如componentWillReceiveProps、shouldComponentUpdate、componentWillUpdate和componentDidUpdate等。这些钩子函数可以帮助我们在组件的不同阶段执行一些必要的操作,以便更好地控制和管理组件的行为。 综上所述,React生命周期钩子是在组件的不同阶段执行特定操作的函数,其中包括实例化阶段、存在期阶段和销毁期阶段。其中getDerivedStateFromProps和getSnapshotBeforeUpdate是在存在期阶段执行的两个重要钩子函数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值