react的生命周期钩子函数

前言:

你有没有遇到过这样的问题:

  • 组件的生命周期有哪些?为什么要有生命周期函数?
  • 我应该什么时候去获取后台数据? 为什么很多教程都推荐用componentDidMount? 用componentWillMount会有什么问题?
  • 为什么setState写在这里造成了重复渲染多次?
  • setState在这里写合适吗?

读完本文希望你能对React的组件生命周期有一定的了解,编写React代码的时候能够更加得心应手,注意本文的生命周期讲的主要是浏览器端渲染,这是后端和全栈的主要使用方式,服务端渲染有些不一样,请注意区分,我们会在文中进行简单说明。

一、首先我们先来掌握基本单词

掌握单词后会更好理解和记住生命周期:

单词意思
constructor构造函数
component组件
will将要
get得到
default默认值
initial最初的
unsafe不安全的
static静态的
derived衍生的
should应该
update更新
unmount取消挂载
receive收到
snap提前
shot拍摄

二、全部生命周期总体分为三个执行阶段:

1.组件挂载

(1)constructor

可以理解为组件的第一个生命周期,一般会在这里初始化组件的内部状态state 或者 进行方法绑定, 如果在这里面要使用this则必须在super()之后,如果在这里面需要使用props,那么需要把props作为参数传入

constructor(props) {
  super(props);
  this.state = {
    color: '#fff',
    num: this.props.num,
  };
}

如果你不需要初始化状态也不需要绑定handle函数的this,那么你可以不实现constructor函数,由默认实现代替。

(2)static getDerivedStateFromProps
这个生命周期只要父组件重新渲染时就会触发。

设置了这个生命周期就不能设置componentWillMount()
这是react16.3之后新增的一个生命周期,这是一个静态方法。
这个函数会在render函数被调用之前调用,包括第一次的初始化组件以及后续的更新过程中,每次接收新的props之后都会返回一个对象作为新的state,返回null则说明不需要更新state

静态方法没有this所以不能使用setState。

(3)componentWillMount ------------ 17版本即将废除

组件将要挂载,这个生命周期基本上没有什么用,而且react*17版本之后废弃。
如果还想继续使用,可以使用UNSAFE_componentWillMount来代替,只不过不可与static getDerivedStateFromProps 混用。

(4)render

react最重要的步骤【React组件的核心方法】,用于根据状态state和属性props创建虚拟dom,进行diff算法,更新dom树都在此进行。此时就不能更改state了。
这里是合成虚拟DOM,可以理解为,在这里实际上都还没有真实的dom。

我们应该保持该方法的纯洁性,这会让我们的组件更易于理解,只要state和props不变,每次调用render返回的结果应当相同,所以请不要在render方法中改变组件状态,也不要在在这个方法中和浏览器直接交互。

(5)componentDidMount ------------- ajax请求生成DOM

componentDidMount方法会在render方法之后立即被调用,该方法在整个React生命周期中只会被调用一次。React的组件树是一个树形结构,此时你可以认为这个组件以及他下面的所有子组件都已经渲染完了,所以在这个方法中你可以调用和真实DOM相关的操作了。

有些组件的启动工作是依赖 DOM 的,例如动画的启动,而 componentWillMount 的时候组件还没挂载完成,所以没法进行这些启动工作,这时候就可以把这些操作放在 componentDidMount 当中。

这个生命周期就是相当重要的一个生命周期,ajax请求一般都在这里进行。

解决一个大家的疑问,为什么不在componentWillMount里面发请求:
1.要废除掉这个生命周期了
2.跟服务端渲染有关系(同构),如果在 componentWillMount 里获取数据,fetch data会执行两次,一次在服务端一次在客户端,使用 componentDidMount 则没有这个问题。




2.组件更新

分为俩种情况,state改变和props改变
如果state改变,会直接进行到组件更新的第二个shouldComponentUpdate,如果是props改变,会先走static getDerivedStateFromProps 或者 componentWillReceiveProps。

(1)static getDerivedStateFromProps
(1.1)componentWillReceiveProps ----- 17版本即将废除

16.4之前,由于在更新阶段,没有static getDeriveStateFromProps这个生命周期,如果有根据props来生成的state,就需要在这里重新设置一次。因为之前是在constructor里面根据props来初始化的state,constructor只会执行一次,所以要在componentWillReceiveProps来修正state。在新的版本里,static getDerivedStateFromProps这个生命周期不管是在装载还是更新的时候都会触发。因此,componentWillReceiveProps也只会工作到react17.后续想要使用的话可以加前缀UNSAFE_,但不可与static getDerivedStateFromProps一同使用。

(2)shouldComponentUpdate 性能优化

这个生命周期用于react的性能优化,接收俩个参数(nextProps,nextState)通常会根据这俩个参数和this.state,this.props来进行对比,根据比较的结果来return true或者false,如果return的是false,将不会再执行后面的生命周期【也就是不会触发渲染】。

注意这个函数如果返回false并不会导致子组件也不更新。

PS: 该函数通常是优化性能的紧急出口,是个大招,不要轻易用,如果要用可以参考Immutable 详解及 React 中实践 .

(3)componentWillUpdate -----17版本即将废除

没什么卵用

(4)render

和mount阶段一样,生成虚拟DOM

(5)getSnapshotBeforeUpdate ----- 在最近一次渲染输出(提交到DOM节点)之前调用。
它使得组件能在发生更改之前从DOM中捕获一些信息(例如,滚动位置)。此生命周期的任何返回值将作为参数传递给componentDidUpdate的第三个参数。

此方法不常用,笔者就没在实战中使用过,官方文档说它可能出现在UI处理中,如需要以特殊方式处理滚动位置的聊天线程等。

(6)componentDidUpdate
接收三个参数,分别是:preProps, preState, snapshot
只有在组件使用了getSnapshotBeforeUpdate生命周期了才会用getSnapshotBeforeUpdate的返回值作为componentDidUpdate生命周期的第三个参数。否则第三个参数为undefined

会在更新后立即被调用,首次渲染不会触发,你可以在这个方法中进行DOM操作,或者做一些异步调用。
一般用来根据判断preProps与this.props或者preState与this.state进行比较从而发请求或进行其他的一些处理。




3.组件销毁

(1)componentWillUnmount

组件将要销毁,这里一般可以用来清理定时器,解绑某些事件,取消网络请求等等。

5.错误处理

(1)static getDerivedStateFromError ------ 会在子组件抛出错误后被调用
它将抛出的错误作为参数,并返回一个值更新state。

注意事项:它会在渲染阶段调用,因此不允许出现副作用【比如请求等】,如遇此类情况,请改用componentDidCatch

(2)componentDidCatch ------ 同上
他接受俩个参数

  1. error 抛出的错误
  2. info 带有componentStack key的对象,其中包含有关组件引发错误的栈信息。

它会在“组件提交”阶段被调用,因此允许执行副作用。它应该用作于记录错误之类的情况。

三、react生命周期执行的三个步骤【速查表】

在这里插入图片描述

四、强制刷新组件 – forceUpdate

默认情况下,当组件的state或props发生变化时,组件将重新渲染。如果render()方法依赖于其他数据,则可以调用forceUpdate()强制让组件重新渲染。

调用这个方法会跳过该组件的shouldComponentUpdate()。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值