通俗易懂了解React生命周期 1.前言 2.生命周期图 3.代码演示 3.各个过程详解

学习React时,学习组件的生命周期是非常重要的,了解了组件的“从无到有再到无”所经历的各个状态,对日后写高性能的组件会有很大的帮助。

2.生命周期图

React的生命周期图示如图所示,其大致分为三个阶段:初始化阶段、更新阶段、销毁阶段。
通俗易懂了解React生命周期
1.前言
2.生命周期图
3.代码演示
3.各个过程详解

上图是一个组件从被创建出来到最后被销毁所要经历的一系列过程,所以这个过程也叫做一个组件的生命周期图。从图中我们可以看到,一个组件从创建到更新最后到被销毁,总共要经历以下几个过程

初始化阶段

  • getDefaultProps()
  • getInitialState()
  • componentWillMount()
  • render()
  • componentDidMount()

更新阶段

  • componentWillReceiveProps(nextProps)
  • shouldComponentUpdate(nextProps, nextState)
  • componentWillUpdata(nextProps, nextState)
  • componentDidUpdate()

销毁阶段

  • componentWillUnmount()

3.代码演示

了解了组件生命周期各个过程后,我们放一波代码,真正的看一看一个组件从生到死到底经历了什么。

import React, {Component} from 'react';
import ReactDOM from "react-dom";

class LifeCycle extends Component {

  constructor(props) {
    super(props)
    this.state = {
      count: 0
    }
  }

  componentWillMount() {
    console.group("%c%s", "color:red", '==============componentWillMount 组件挂载之前===============');
    console.log('element:', document.querySelector('#lifecycle'));
  }

  componentDidMount() {
    console.group("%c%s", "color:red", '==============componentDidMount 组件挂载完毕===============');
    console.log('element:', document.querySelector('#lifecycle'));
  }

  componentWillUpdate(nextProps, nextState, nextContext) {
    console.group("%c%s", "color:red", '==============componentWillUpdate 组件更新之前===============');
    console.log('element:', document.querySelector('#lifecycle'));
  }

  componentDidUpdate(prevProps, prevState, snapshot) {
    console.group("%c%s", "color:red", '==============componentDidUpdate 组件更新完毕===============');
    console.log('element:', document.querySelector('#lifecycle'));
  }

  componentWillUnmount() {
    console.group("%c%s", "color:red", '==============componentWillUnmount 组件销毁完毕===============');
    console.log('element:', document.querySelector('#lifecycle'));
  }

  add = () => {
    this.setState({
      count: this.state.count + 1
    })
  }

  destory = () => {
    ReactDOM.unmountComponentAtNode(document.querySelector('#root'))
  }

  render() {
    console.group("%c%s", "color:red", '==============render 组件正在挂载===============');
    console.log('element:', document.querySelector('#lifecycle'));
    return (
      <div id='lifecycle'>
        <h1>计数器:{this.state.count}</h1>
        <button onClick={this.add}>+</button>
        <button onClick={this.destory}>销毁</button>
      </div>
    );
  }
}

export default LifeCycle;

运行上面代码,可以看到如下效果:

通俗易懂了解React生命周期
1.前言
2.生命周期图
3.代码演示
3.各个过程详解

3.各个过程详解

3.1 getDefaultProps()

设置默认的props,也可以用dufaultProps设置组件的默认属性.

3.2 getInitialState()

在使用class语法时是没有这个钩子函数的,可以直接在constructor中定义this.state。此时可以访问this.props

3.3 componentWillMount()

此钩子函数在组件挂载之前被调用,从控制台打印结果可以看出,此时组件的DOM节点还未被创建,可以修改state.

通俗易懂了解React生命周期
1.前言
2.生命周期图
3.代码演示
3.各个过程详解

3.4 render()

该函数为整个生命周期中最重要的步骤,该步骤会创建虚拟dom,进行diff算法,更新dom树。

render() 函数应该为纯函数,这意味着在不修改组件 state 的情况下,每次调用时都返回相同的结果,并且它不会直接与浏览器交互。

如需与浏览器进行交互,请在 componentDidMount() 或其他生命周期方法中执行你的操作。保持 render() 为纯函数,可以使组件更容易思考。

3.5 componentDidMount()

此钩子函数在组件挂载完毕后调用,从控制台打印结果可以看出,此时组件的DOM节点已经被成功挂载(插入 DOM 树中)。依赖于 DOM 节点的初始化应该放在这里。如需通过网络请求获取数据,此处是实例化请求的好地方。

3.6 componentWillReceiveProps(nextProps)

此钩子函数在组件接受到新的props时被调用。

3.7 shouldComponentUpdate(nextProps, nextState)

react性能优化非常重要的一环。组件接受新的state或者props时调用,我们可以设置在此对比前后两个propsstate是否相同,如果相同则让该函数返回false阻止更新(返回值默认为 true),因为相同的属性状态一定会生成相同的dom树,这样就不需要创造新的dom树和旧的dom树进行diff算法对比,节省大量性能,尤其是在dom结构复杂的时候。

例如,在本文的例子中,我们使得当计数器大于3时,不再更新。可以编写如下代码:

shouldComponentUpdate(nextProps, nextState, nextContext) {
    if (nextState.count > 3) {
      return false
    } else {
      return true
    }
  }

通俗易懂了解React生命周期
1.前言
2.生命周期图
3.代码演示
3.各个过程详解

从图中我们可以看到,当计数器等于3时,再点击“+”号时,组件已经不再更新了。

3.8 componentWillUpdata(nextProps, nextState)

当组件收到新的 props 或 state 时,会在渲染之前调用此钩子函数。使用此函数可作为在组件更新发生之前需要执行的相关操作。初始渲染不会调用此方法。

注:如果 shouldComponentUpdate() 返回 false,则不会调用componentWillUpdate()

3.9 componentDidUpdate()

此钩子函数会在组件更新后会被立即调用。首次渲染不会执行此方法。

当组件更新后,可以在此处对 DOM 进行操作。如果你对更新前后的 props 进行了比较,也可以选择在此处进行网络请求。(例如,当 props 未发生变化时,则不会执行网络请求)。

componentDidUpdate(prevProps) {
  // 典型用法(不要忘记比较 props):
  if (this.props.userID !== prevProps.userID) {
    this.fetchData(this.props.userID);
  }
}

注:如果 shouldComponentUpdate() 返回值为 false,则不会调用 componentDidUpdate()

3.10 componentWillUnmount()

componentWillUnmount() 会在组件卸载及销毁之前直接调用。在此方法中执行必要的清理操作,例如,清除 timer,取消网络请求或清除在 componentDidMount() 中创建的订阅等。

componentWillUnmount()不应调用 setState(),因为该组件将永远不会重新渲染。组件实例卸载后,将永远不会再挂载它

(完)