zoukankan      html  css  js  c++  java
  • 通俗易懂了解React生命周期

    1.前言

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

    2.生命周期图

    React的生命周期图示如图所示,其大致分为三个阶段:初始化阶段、更新阶段、销毁阶段。

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

    初始化阶段

    • 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;
    

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

    3.各个过程详解

    3.1 getDefaultProps()

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

    3.2 getInitialState()

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

    3.3 componentWillMount()

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

    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
        }
      }
    

    从图中我们可以看到,当计数器等于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(),因为该组件将永远不会重新渲染。组件实例卸载后,将永远不会再挂载它

    (完)

  • 相关阅读:
    JavaScript之正则表达式
    BOM之本地数据存储
    BOM之定时器
    BOM之window核心模块
    BOM简介
    DOM之元素定位
    DOM之事件
    DOM之节点操作
    DOM简介
    linux机制
  • 原文地址:https://www.cnblogs.com/wangjiachen666/p/10882627.html
Copyright © 2011-2022 走看看