React生命周期

生命周期函数,也叫做生命周期钩子,是react为我们提供的,可以在一些特定时间点进行操作的API方法。例如在组件挂载完成后请求后台数据,或是在组件销毁时清除定时器等

生命周期钩子(旧)

请添加图片描述
旧版本为react v17.0以前使用的版本。简单介绍一下图中的生命周期钩子。

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

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

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

			//控制组件更新的“阀门”,通过返回的布尔值来判断是否要更新组件
			shouldComponentUpdate(){
				console.log('Count---shouldComponentUpdate');
				return true
			}

			//组件将要更新的钩子
			componentWillUpdate(){
				console.log('Count---componentWillUpdate');
			}

			//组件更新完毕的钩子
			componentDidUpdate(){
				console.log('Count---componentDidUpdate');
			}
			//子组件
			//组件将要接收新的props的钩子,接收一个参数,为传入的props
			componentWillReceiveProps(props){
				console.log('B---componentWillReceiveProps',props);
			}

如图所示,可以分为三个阶段,生命周期调用顺序如下

  • 初始化阶段: 由ReactDOM.render()触发—初次渲染
    1. constructor()
    2. componentWillMount()
    3. render()
    4. componentDidMount() =====> 常用
    一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息
  • 更新阶段: 由组件内部this.setSate()或父组件render触发
    1. shouldComponentUpdate()
    2. componentWillUpdate()
    3. render() =====> 必须使用的一个
    4. componentDidUpdate()
  • 卸载组件: 由ReactDOM.unmountComponentAtNode()触发
    1. componentWillUnmount() =====> 常用
    一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息

生命周期钩子(新17.0)

请添加图片描述
在react v17.0版本以上,官方建议使用新版生命周期钩子。
如图所示,相比于旧版本的生命周期,移除了三个will的钩子: componentWillMount();componentWillUpdate();componentWillReceiveProps();并不是删除了,依然可以在代码中使用,但是会提示添加UNSAFE_前缀。提醒开发者将来可能会移除这些钩子。
添加了两个新的钩子:getDerivedStateFromProps();getSnapshotBeforeUpdate();


新生命周期钩子调用顺序:

  • 初始化阶段: 由ReactDOM.render()触发—初次渲染
    1. constructor()
    2. getDerivedStateFromProps
    3. render()
    4. componentDidMount() =====> 常用
    一般在这个钩子中做一些初始化的事,例如:开启定时器、发送网络请求、订阅消息
  • 更新阶段: 由组件内部this.setSate()或父组件重新render触发
    1. getDerivedStateFromProps
    2. shouldComponentUpdate()
    3. render()
    4. getSnapshotBeforeUpdate
    5. componentDidUpdate()
  • 卸载组件: 由ReactDOM.unmountComponentAtNode()触发
    1. componentWillUnmount() =====> 常用
    一般在这个钩子中做一些收尾的事,例如:关闭定时器、取消订阅消息

getDerivedStateFromProps

这个钩子翻译过来的意思就是从props中获取state,这个函数会在每次render之前被调用,即使你的props没有任何变化,而是父组件发生变化,导致子组件发生了re-render,这个生命周期函数依然会被调用。官方推荐使用在当state值在任何时候都取决于props时。

作为componentWillReceiveProps的替代钩子,用法有很大区别,getDerivedStateFromProps是一个静态函数,需要添加static前缀,并且无法通过this来获取组件实例。

getDerivedStateFromProps需要返回一个状态对象(state)或者null

//接收两个参数,一个是传入的props,另一个是当前组件的state
static getDerivedStateFromProps(props, state) {
    const {type} = props;
    // 当传入的type发生变化的时候,更新state
    if (type !== state.type) {
        return {
            type,
        };
    }
    // 否则,对于state不进行任何操作
    return null;
}

官方文档说明,使用这个钩子可能会导致代码冗余,且难以维护,了解即可。

getSnapshotBeforeUpdate

getSnapshotBeforeUpdate(prevProps, prevState)方法按翻译语义化理解就是“获得更新之前的快照”,也就是可以在组件更新之后保存更新前的状态。可以接收两个参数,一个是更新前的props,第二个是更新前的state。该钩子始终与componentDidUpdate()方法一起使用,返回值将传递给componentDidUpdate()方法的第三个参数。

举个例子,模拟一个弹幕自动刷新的效果,旧的弹幕在下,新的弹幕在上,当超出弹幕框高度后旧的会被挤出可视区域,导致可视区滚动。现在需要实现,当弹幕超出高度时,继续在弹幕框中刷新,但是可视区域不会滚动。
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<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>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值