本篇目录:

  • 挂载阶段
    • constructor
    • componentWillMount
    • render
    • componentDidMount
  • 更新阶段
    • componentWillReceiveProps(nextProps)
    • shouldComponentUpdate(nextProps, nextState)
    • componentWillUpdate(nextProps, nextState)
    • componentDidUpdate(prevProps, prevState)
  • 卸载阶段
    • componentWillUnmount
  • 结语

组建从被创建到被销毁的过程称为组件的生命周期。React为组件在不同的生命周期阶段提供了不同的生命周期方法,可以让我们在组件的生命周期过程中更好的控制组件的行为。通常生命周期我们可以分为三个阶段:
挂载阶段 -> 更新阶段 -> 卸载阶段

挂载阶段

此阶段组件被创建,执行初始化,并被挂载到DOM中,完成组件第一次渲染。

挂载阶段

constructor

constructor本身是ES6的class的构造方法,组件被创建时,会首先调用组件的构造方法。这个构造方法会接受一个props参数,props是从父组件传过来的属性对象,如果父组件没有传入属性而组件自身定义了默认属性,那么这个props指向的就是组件的默认属性。

而且很关键的是,你必须在这个方法中先调用super(props)才能保证props被传入组件中,这部分具体的大家参照ES6中class相关内容就可以了。

constructor通常用于初始化组件的state以及绑定事件处理函数等。

componentWillMount

该方法在组件被挂载到DOM前调用,且只会被调用一次。这个方法实际上很少被用到,相关阶段的处理完全可以放到constructor中。

在这个方法中调用this.setState不会引起组件的重新渲染。

render

该方法是组件定义时唯一必要的方法(组件的其他生命周期函数都可以忽略)。在这个方法中,根据组件的propsstate返回一个React元素,用于描述组件的UI,通常React元素使用JSX语法定义。
需要注意的是,render并不负责组件的实际渲染工作,它只是返回了一个UI的描述,真正的渲染出页面DOM的工作是由React自身负责。
render是一个纯函数,在这个方法中不能执行任何有‘副作用’的操作,所以不能在render方法中调用this.setState,这会改变组件的状态,导致程序出现问题。

componentDidMount

在组件被挂载到DOM后将会调用这个方法,且只会被调用一次。这个时候已经可以获取到DOM结构,因为依赖DOM节点的操作可以放到这个方法中。这个方法通常还会用于向服务器请求数据。在这个方法中调用this.setState会引起组件的重新渲染。

更新阶段

组件被挂载到DOM后,组件的propsstate可以引起组件更新。props引起的组件更新,本质上是由渲染该组件的父组件引起的,也就是当父组件的render方法被调用时,组件会发生更新过程。这个时候,组件的props的值是否变更是由父组件来决定的,但是,无论props是否变化,父组件render方法每被调用一次,都会导致组件更新。

state引起的更新过程,是通过调用this.setState修改组件的state来触发的。

更新阶段

componentWillReceiveProps(nextProps)

看名称也可以猜到,这个方法和props有关。这个方法只会在props引起的组件更新过程中,才会被调用。
State引起的组件更新并不会触发该方法。方法的参数nextProps是父组件传递给当前组件的新的props。在前面我们也提到过,父组件render方法的调用并不能保证传递给子组件的props发生变化,也就是说nextProps不一定发生变化,因为往往我们需要先比较nextPropsthis.props来决定是否执行props发生变化后的逻辑。比如根据新的props来更新state触发组件的重新渲染。

componentWillReceiveProps中调用setState,只有在组件render及其之后的方法中,this.state指向的才是更新后的state。在render之前的方法(shouldComponentUpdatecomponentWillUpdate)中,this.state依然指向更新前的state

通过调用setState更新组件状态并不会触发componentWillReceiveProps的调用,否则可能会进入死循环,componentWillReceiveProps -> this.setState -> componentWillReceiveProps -> this.setState -> ……

shouldComponentUpdate(nextProps, nextState)

这个方法决定组件是否继续执行更新过程。当方法返回true时(true也是这个方法的默认返回值),组件会继续更新过程;当方法返回false时,组件的更新过程将停止,后续的componentWillUpdaterendercomponentDidUpdate也不会被调用。

一般通过比较nextPropsnextState的组件当前的propsstate决定这个方法的返回结果。这个方法可以用来减少组件不必要的渲染,从而优化组件的性能。

componentWillUpdate(nextProps, nextState)

这个方法在组件render调用前执行,可以作为组件更新发生前执行某些工作的地方,一般也较少用到。

shouldComponentUpdatecomponentWillUpdate中都不能调用setState,否则会引起循环调用问题,render永远无法被调用,组件也就不能被更新了。

componentDidUpdate(prevProps, prevState)

组件更新后调用,可以作为操作更新后的DOM的地方,这个方法的两个参数prevPropsprevState代表组件更新前的propsstate

卸载阶段

该过程是组件从DOM中被卸载的过程,该过程只有一个生命周期方法:componentWillUnmount

componentWillUnmount

这个方法在组件被卸载前调用,可以在这里执行一些清理工作,比如清除组件中使用的定时器,清除componentDidMount中手动创建的DOM元素等,以避免引起内存泄露。

结语

上面我们简单梳理分析了React组件的生命周期方法的不同阶段的执行过程,以及每个生命周期方法的功能的作用。最后要提醒大家,只有类组件才具有生命周期方法,函数组件是没有生命周期方法的。


参考资料:

React中文文档
《React进阶之路》