React系列之新旧生命周期对比

生命周期

React 实例从创建到销毁的全过程就是生命周期,钩子函数是指程序运行到特定阶段执行的方法。React 的生命周期在不断演进,在16.3版本前后有较大改变。

旧生命周期

在这里插入图片描述

初始化阶段:由 ReactDOM.render() 触发,初次渲染,会调用以下钩子函数:
1.constructor() 构造函数,通常用于初始化组件的状态和绑定方法。
2.componentWillMount() 代表组件已经经历了constructor()初始化数据后,但是还未渲染DOM时。
3.render() 是用来返回组件的UI结构
4.componentDidMount() 在组件挂载到DOM后执行的,可以在这里获取数据、进行一些异步请求或DOM操作。

更新阶段:由组件内部 this.setState 或父组件重新 render 触发,会调用以下钩子函数:
1.componentWillRecieveProps(nextProps) 在接受父组件改变后的props需要重新渲染组件时使用。
1.shouldComponentUpdate(nextProps, nextState) 用来判断组件是否需要重新渲染,返回一个布尔值,可以优化性能。例如父组件重新渲染会使其所有子组件重新渲染,如果我们不需要所有子组件都重新渲染,可以在子组件的该生命周期中做判断。
2.componentWillUpdate(nextProps, nextState) 当调用forceUpdate()时,会直接来到componentWillUpdate()钩子函数。
3.render()
4.componentDidUpdate(prevProps, prevState) 组件更新后触发,用于处理更新后的操作。

卸载组件:由 ReactDOM.unmountComponentAtNode() 触发。
1.component1WillUnmount() 在组件卸载前执行的,可以在这里进行一些清理工作,比如取消订阅、清除定时器、取消异步请求或移除事件监听器等。

新生命周期

在这里插入图片描述

初始化阶段,由ReactDOM.render()触发——初次渲染:
1.constructor()
2.getDerivedStateFromProps()
3.render()
4.conponentDidMount()

更新阶段,由组件内部this.setState()或父组件重新render触发
1.getDerivedStateFromProps()
2.shouldComponentUpdate()
3.render()
4.getSnapshotBeforeUpdate()
5.componentDidUpdate()

卸载阶段,由ReactDOM.unmountCompopnentAtNode()触发
1.componentWillUnmount()

新旧对比

删除生命周期及原因

删除:新的生命周期中不再使用以下三个钩子函数componentWillMount()、componentWillReceiveProps(nextProps)、componentWillUpdate(nextProps, nextState)

原因:在 React 16 版本中,引入了 Fiber 架构,它是一种重新实现了调度算法的 React 内部架构。Fiber 架构的引入使得 React 能够支持更加细粒度的调度和异步渲染,从而提高了性能和用户体验。
在 React 16 之前,React 使用了一种称为 Stack Reconciler 的调度算法,它是一种递归算法,采用了深度优先遍历的方式进行组件的渲染和更新。这种算法有一个问题就是,一旦开始了渲染过程,就无法中断或暂停,直到整个渲染过程完成。这意味着如果渲染过程很耗时,可能会导致页面卡顿,用户体验下降。
为了解决这个问题,React 引入了 Fiber 架构。Fiber 架构采用了一种基于链表的调度算法,使得 React 能够在渲染过程中实现任务的中断、暂停和优先级控制,从而实现了异步渲染的能力。具体来说,Fiber 架构通过将渲染过程拆分为多个小的任务单元,然后通过优先级调度和时间分片的方式来动态地调度这些任务单元的执行顺序,以确保页面的流畅度和响应速度。
Filber 的机制下,生命周期分为 render 和 commit 的阶段,render 的时候是可以被打断的,重新渲染,终止的,当一个任务执行到一半被打断后,下一次渲染线程抢回主动权时,这个任务被重启的形式是“重复执行一遍整个任务”而非“接着上次执行到的那行代码往下走”。这就导致 render 阶段之前的生命周期都是有可能被重复执行的,所以这三个生命周期被废除了。

改变的生命周期

componentDidUpdate(prevProps,prevState,snapshot):它在组件更新后被调用。它接收三个参数:prevProps、prevState、snapshot。与旧的钩子函数相比,多了一个参数snapshot。
如果 getSnapshotBeforeUpdate() 有返回值,它会成为 componentDidUpdate() 的第三个参数,你可以在这里使用它。

新增的生命周期

getDerivedStateFromProps(nextProps,prevState):是一个静态方法,用于在组件接收新的 props 时计算并返回新的 state。这个方法在 React 16.3 版本之后引入,用来替代不推荐使用的componentWillReceiveProps()方法。

    static getDerivedStateFromProps(nextProps, prevState) { 
        // 根据 nextProps 和 prevState 计算并返回新的 state 
        if (nextProps.value !== prevState.value) { 
            return { value: nextProps.value }; 
        } 
        return null; // 如果不需要更新 state,返回 null 
    } 

主要作用:
计算新的state:通常,你可以在这个方法内部根据 nextProps 和 prevState 来计算并返回新的state。这个新的 state 将在组件更新时应用。
不触发副作用:getDerivedStateFromProps() 不应执行副作用,如发起网络请求。它只用于计算state。
适用于控制组件内部状态:getDerivedStateFromProps() 主要用于控制组件内部的状态,以确保它与外部传入的props保持同步。

getSnapshotBeforeUpdate(nextProps,prevState):它在组件更新(即将应用新props或state并重新渲染)之前触发。它允许你捕获组件更新前的一些信息,并在组件更新后使用这些信息。

getSnapshotBeforeUpdate(prevProps, prevState) {
	  // 捕获组件更新前的滚动位置
	  if (prevProps.items.length < this.props.items.length) {
		const scrollHeight = this.myRef.current.scrollHeight;
		const scrollTop = this.myRef.current.scrollTop;
		return { scrollHeight, scrollTop };
	  }
	  return null;
	}
    
	componentDidUpdate(prevProps, prevState, snapshot) {
	  // 使用snapshot来恢复滚动位置
	  if (snapshot !== null) {
		this.myRef.current.scrollTop = snapshot.scrollTop + (this.myRef.current.scrollHeight - snapshot.scrollHeight);
	  }
	}
 
getSnapshotBeforeUpdate() 用于捕获滚动位置,然后在componentDidUpdate() 中使用snapshot来恢复滚动位置,以确保用户在滚动列表时不会在更新后失去滚动位置。

主要特点:
触发时机:getSnapshotBeforeUpdate() 在render() 方法被调用后、组件DOM更新前触发,通常用于在更新前捕获一些DOM信息。
接收两个参数:这个生命周期方法接收两个参数:prevProps、prevState。你可以使用这些参数来比较前后的props和state。
返回值:getSnapshotBeforeUpdate() 方法应该返回一个值(通常是一个对象),它将成为componentDidUpdate() 方法的第三个参数。这个返回值通常用于保存一些DOM相关的信息,比如滚动位置。
通常和componentDidUpdate()一起使用:getSnapshotBeforeUpdate() 结合componentDidUpdate(prevProps, prevState, snapshot) 使用,snapshot参数是getSnapshotBeforeUpdate() 的返回值。你可以在componentDidUpdate() 中使用snapshot来执行DOM操作或其他一些操作。

  • 22
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值