likes
comments
collection
share

12-react生命周期钩子函数

作者站长头像
站长
· 阅读数 24

在react中,对于每一次由状态改变导致视图改变的操作,都会经历两个阶段:render和commit阶段。

只有在类组件中才有生命周期,因为类组件会创建对应的实例;而函数组件不会。

生命周期:组件实例从被闯进啊到被销毁的过程成为组件的生命周期。

由class组件创建的实例是具有生命周期的,它的render函数就在render阶段执行,并且内部的diff算法会自动计算哪个DOM发生变化进而去操作。在commit阶段将对应的DOM节点提交到视图上完成显示。

render()阶段

render阶段会执行很多钩子函数,例如:在首次渲染时执行constructor,getDerivedStateFromProps,componentWillMount,render

在执行更新时:componentWillReceiveProps,shouldComponentUpdate,componentWillUpdate,render

在渲染阶段如果捕捉到了组件中的错误,则会执行getDerivedStateFromError

接下来说说每个调用时期与作用。

constructor

该方法只会调用一次,所以可以实现this的一次性绑定。

在初始化阶段,可以This.state为状态赋值,也可以设置一些静态的数据。

componentWillReceiveProps(旧的)

如果组件接收到了新的props,则会第一时间触发这个函数。

在首次渲染组件的时候不会调用此生命周期钩子函数;使用this.setState()也不会触发此生命周期钩子函数。

但,如果是父组件渲染导致自组件的重新渲染,即使传给子组件的props没变,该组件中的这个生命周期函数也会被调用。

我们一般不使用该函数。

getDerivedStateFromProps(新的)

它是一个静态方法,会接受props和state两个参数。他会在调用render方法之前被调用。无论是初始render还是gengxinrender都会触发它。

像他的名字一样,可以从props中获取衍生的state。它的调用时机和 componentWillMount、componentWillUpdate、componentWillReceiveProps 一样都是在 render 方法被调用之前,它可以作为 componentWillMount、componentWillUpdate 和 componentWillReceiveProps 的替代方案。

shouldComponentUpdate

在组件准备更新之前调用,可以把它看成是一个问句:should component update? yes/no

在它的函数中会判断一个组件是否应该更新。但forceupdate不会调用该方法。

它接收两个参数,nextProps 和 nextState,即下一次更新的 props 和下一次更新的 state。我们可以将 this.props 和 nextProps 比较,以及将 this.state 与 nextState 比较,并返回 false,让组件跳过更新。不过注意:它并不会阻止子组件因为 state 改变而导致的更新。

componentWillMount(UNSAFE)

在组件挂载到DOM之前调用一次,并且只会调用一次。它在render方法之前调用,因此在componentWillMount中调用setState不会触发额外的渲染。

componentWillUpdate(UNSAFE)

在组件即将更新之前执行,如果 shouldComponentUpdate 函数返回 false,则不会调用 componentWillUpdate 方法。

这个生命周期钩子和 componentWillMount 类似,执行的时机是相同的,只不过 componentWillMount 在组件首次渲染时执行,而 componentWillUpdate 在组件后续更新时执行。这两个生命周期函数都不经常使用。

render

render函数作为纯函数,他总是返回相同的渲染结果。

render函数被调用时,会返回各种类型。

但如果在shouldComponentUpdate中返回false,则render不会执行。

commit阶段

commit 阶段在首次渲染时会执行 componentDidMount,在组件更新时会执行 getSnapshotBeforeUpdate 和 componentDidUpdate。

componentDidMount

该生命周期方法会在组件挂载之后执行,也只会执行一次,也就是将组件对应的 DOM 插入 DOM 树中之后调用。它会在浏览器更新视图之前调用,如果在 componentDidMount 中直接调用 this.setState,它会触发额外的渲染,会再一次调用 render 函数,但是浏览器中视图的更新只会执行一次。

使用场景:

依赖于 DOM 的初始化操作应该放在这里,此外,我们一般在这个生命周期方法中发送网络请求添加订阅等。

getSnapshotBeforeUpdate(旧的)

此生命周期函数在最近一次渲染提交至 DOM 树之前执行,此时 DOM 树还未改变,我们可以在这里获取 DOM 改变前的信息,例如:更新前 DOM 的滚动位置。

它接收两个参数,分别是:prevProps、prevState,上一个状态的 props 和上一个状态的 state。它的返回值将会传递给 componentDidUpdate 生命周期钩子的第三个参数。

使用场景:

需要获取更新前 DOM 的信息时。例如:需要以特殊方式处理滚动位置的聊天线程等。

componentDidUpdate

在组件更新后立即调用,首次渲染不会调用该方法。它的执行时机和 componentDidMount 一致,只是 componentDidMount 在首次渲染时调用,而 componentDidUpdate 在后续的组件更新时调用。可以在这个生命周期中直接调用 this.setState,但是必须包裹在一个条件语句中,否则会导致死循环。

componentDidUpdate 接收三个参数,分别是 prevProps、prevState、snapshot,即:前一个状态的 props,前一个状态的 state、getSnapshotBeforeUpdate 的返回值。

如果组件实现了 getSnapshotBeforeUpdate 生命周期函数,则 getSnapshotBeforeUpdate 的返回值将作为 componentDidUpdate 的第三个参数。

使用场景:

在这个生命周期方法中,可以对 DOM 进行操作或者进行网络请求

componentWillUnmount

这个生命周期函数会在组件卸载以及销毁之前调用。

使用场景:

通常用来执行组件的清理操作,例如:清除 timer、取消网络请求、清除订阅等。

父子组件生命周期函数调用顺序

父组件 App、子组件 Child1、子组件 Child2

首次渲染:

旧的:

12-react生命周期钩子函数

  • 首先依次执行父组件 render 阶段的生命周期函数;
  • 然后依次执行子组件 render 阶段的生命周期函数;
  • 最后交叉执行子组件和父组件 commit 阶段的生命周期函数。

对于 render 阶段的生命周期函数,其顺序是 父组件 -> 子组件;而对于 commit 阶段的生命周期函数,其顺序是 子组件 -> 父组件

新的:

12-react生命周期钩子函数

getDerivedStateFromProps 的执行顺序基本上替代了 componentWillMount 的执行顺序。

但是需要注意:getDerivedStateFromProps 是一个静态方法,不能通过 this 获取到组件实例,如果我们要拿到组件的 props 和 state,必须要通过参数才能拿到。而在 componentWillMount 中,则是通过 this.props 拿到 props。

子组件状态改变:

旧的,点击子组件后:

12-react生命周期钩子函数

子组件状态改变不会执行componentWillReceiveProps。

新的:

12-react生命周期钩子函数

父组件状态改变:

旧的:点击父组件后:

12-react生命周期钩子函数

新的:

12-react生命周期钩子函数

cr大佬文章地址:juejin.cn/post/709613…