React(8)React组件的生命周期

前言

本篇文章我们来系统的讲解React组件的生命周期。React随着版本的不断提升,组件的生命周期也在不断地改版和升级。本篇文章以React 17为例,讲解最新版React的组件生命周期,同时阐述各个生命周期所执行的生命周期函数。


一、React组件的生命周期

React 17将组件的生命周期分为以下三个阶段:

  • 组件的挂载阶段(Mounting)
  • 组件的更新阶段(Updating)
  • 组件的卸载阶段(Unmounting)

二、React组件的挂载阶段

在React中,将组件第一次插入至DOM树中渲染的过程称之为“挂载”。挂载阶段要完成组件状态的初始化、创建API调用请求、启动或停止计时器、操作已渲染的DOM、初始化第三方脚本库等工作。React组件挂载阶段涉及到以下四个生命周期函数。

  • constructor()
  • getDerivedStateFromProps()
  • render()
  • componentDimMount()

1、constructor()构造函数

从原理上来讲,constructor()构造函数并不是一个生命周期函数,只是当组件挂载时,构造函数永远是第一个被触发的。构造函数的主要功能是初始化组件状态,即为state区设置初始化数据。
构造函数的格式如下所示。

class Comp extends react.Component{
  constructor(props){
    super(props);
    this.state={
      // 初始化React组件状态
    }
  }
} 

2、getDerivedStateFromProps()生命周期函数

该函数是一个静态函数,使用时必须声明static关键字,且不能在其内部使用this关键字。同时使用时有两个参数:nextProps、prevState,分别用来表示父组件传递过来的参数对象和组件的state区数据对象。该生命周期函数在使用时有如下规定。

  • 组件必须在constructor()构造函数中设置state区,否则该函数会报错。
  • 该生命周期函数必须返回一个对象,或者返回null。

从这个生命周期函数的名字中就可以看出,它的功能是从props中获取state,即利用父组件传递过来的props属性来更新state数据。

例1:父组件调用子组件,并向Comp传递title和content两个参数。

父组件核心代码:

 

子组件代码:

class Comp extends React.Component{
  constructor(props){
    super(props);
    this.state={
      ca:15,
      cb:20
    }
    console.log(this.state);
  }
  static getDerviedStateFromProps(nextProps,prevState){
    console.log(nextProps);
    console.log(prevState);
    const {title,content} = nextProps;
    return {
      title,content
    }
  }
} 

在上述代码中,组件Comp挂载阶段,先执行构造函数constructor(),再执行静态函数getDerviedStateFromProps()。所以在构造函数中输出this.state,结果为:{ca:15,cb:20}。

静态函数getDerviedStateFromProps()中nextProps参数是父组件向子组件传递的数据构成的对象,所以输出nextProps的结果为:{title:“组件挂载”,content:“将组件第一次插入至DOM树中渲染”}。

静态函数getDerviedStateFromProps()中返回的对象都是要加入到组件的state状态中的,所以父组件向子组件传递的title数据和content数据也会变为state状态区中的一部分。

3、render()渲染函数

render()渲染函数是React组件的必备函数,没有该函数React组件会报错。该函数用来返回使用JSX语法实现的组件内容,包括HTML标记对和JavaScript业务流程。在例1中,如果在render()函数中输出this.state,因为getDerviedStateFromProps()函数在render()函数之前执行,所以此时输出的结果为:{ca:15,cb:20,title:“组件挂载”, content:“将组件第一次插入至DOM树中渲染”}。

4、componentDidMount()生命周期函数

该函数是组件挂载阶段最后一个执行的生命周期函数,会在组件挂载成功且渲染完毕之后触发。项目开发过程中,多在该函数中调取API数据,例如使用Fetch、Axios技术从后台获取组件使用的数据。

三、React组件的更新阶段

在React中,将组件重新渲染的过程称之为“更新”。当组件的state数据发生变化或从父组件接收到新的属性时进入到组件的更新阶段,即调用this.setState()方法时,组件会启动更新阶段。React组件更新阶段涉及到以下五个生命周期函数。

  • getDerviedStateFromProps()
  • shouldComponentUpdate()
  • render()
  • getSnapshotBeforeUpdate()
  • componentDidUpdate()

首先,要重点声明。上述函数都是在组件更新时触发的生命周期函数,即一旦执行了this.state()方法,上述函数就会依次执行一遍。也就是说,如果在上述函数中调用了this.state()方法,将会使更新生命周期引发无限递归循环,从而导致堆栈溢出。因此上述函数中不得调用this.state()方法。render()函数中元素的事件函数除外,因为事件函数虽然书写在render()函数内部,但是并不自动执行,因此不会导致堆栈溢出。

1、shouldComponentUpdate()生命周期函数

该生命周期函数有两个参数:nextProps、prevState,分别用来表示父组件传递过来的参数对象和组件的state区数据对象。
该生命周期函数被称为更新阶段的“门卫”,在使用时必须返回一个逻辑值,以表示后面的更新生命周期函数是否继续执行。

  • 返回true,表示继续执行组件的更新生命周期函数。
  • 返回false,表示不再继续执行组件的更新生命周期函数。

这里需要注意,该生命周期函数返回false,只表示不再继续执行后面的生命周期函数,触发更新声明周期启动的this.setState()方法依然会成功执行。

例2:当更新state区中的title数据时,判断父组件传递的title是否与更新后的title一致,如一致就停止执行生命周期过程;如不一致则继续执行生命周期过程。
class Comp extends Component {
  constructor(props){
    super(props);
    this.state={
      ca:15,
      cb:20
    };
  }
  shouldComponentUpdate(nextProps,prevState){
    if(nextProps.title!==prevState.title){
      return true;
    }
    return false;
  }
  btnClick(){
    this.setState({
      title:"你好"
    })
  }
  render() {
    console.log("Render函数");
    console.log(this.state);
    return (
      
        我是Comp组件
        

); } }

2、getSnapshotBeforeUpdate()生命周期函数

该生命周期函数在组件的更新阶段,在render()函数之后,组件DOM渲染之前触发。具备以下两个参数。

  • prevProps:依然表示父组件向子组件传递的数据。
  • prevState:依然表示state区中的数据。

该生命周期函数在使用时有如下两个规定:

  • 必须配合componentDidUpdate()生命周期函数共同使用。
  • 必须返回一个值,该值将作为componentDidUpdate()生命周期函数的第三个参数。

3、componentDidUpdate()生命周期函数

该生命周期函数在组件更新完成后触发,其语法格式如下所示。
componentDidUpdate(prevProps,prevState,snapshot){}

四、React组件的卸载阶段

在React中,从DOM树中删除组件的过程称之为“卸载”。该生命周期只有一个生命周期函数。

  • componentWillUnmount()

可以在该生命周期函数中清除timer计时器以及在componentDidMount()生命周期函数中声明的变量。


总结

本文是React系列教程的第八篇文章,主要为大家讲解了React 17中组件的生命周期与各个生命周期的函数。整体来说,生命周期函数的执行可以用下图来进行说明。
在这里插入图片描述

关于作者

小海前端,具有18年Web项目开发和前后台培训经验,在前端领域著有较为系统的培训教材,对Vue.js、微信小程序开发、uniApp、React等全栈开发领域都有较为深的造诣。入住Segmentfault,希望能够更多的结识Web开发领域的同仁,将Web开发大力的进行普及。同时也愿意与大家进行深入的技术研讨和商业合作。

你可能感兴趣的