• react入门系列之生命周期钩子函数


    什么是生命周期函数

    1. 组件中在某个阶段会自动执行的函数。
      • 比如我们执行使用render函数,在prop或者state变化时,render函数自动执行。
      • 因此render函数就是一个生命周期函数。
    2. constructor在组件创建的时候也会自动调用。但是他不是react独有,是es6中的函数所以,我们不将他列为生命周期函数。

    生命周期分为4个阶段

    1. initialization(组件初始化)
      • 我们在创建组件的时候需要继承react Component这个基类,也就继承这个react的基类,才能有render(),生命周期等方法可以使用,这也说明为什么函数组件不能使用这些方法的原因。同时也让组件能使用setState方法。
      • 然后我们在 constructor 构造函数中使用 super(props)来将父组件传递的props注入给这个组件,以及使用this.state初始化这个组件的属性。
      • 这一系列动作就是组件的初始化。
    2. mount (组件的挂载)
      • 此阶段分为三个时期
        1. componentWillMount(挂载之前)

          • 这个函数在组件挂载到DOM之前的时候执行,所以你在这里引用setState方法,是不会引起组件的重新渲染。
          • 同样这里做的事情如果放在constructor构造函数中去使用也是可以的。
          • 这个函数只会被调用一次,就是组件挂载到DOM之前的时候。其他时候是不会触发这个函数的。
        2. render(挂载中)

          • 根据组件的props和state是否变化,变化即执行,这里的变化要注意,并不是值变化。只要重新赋值,新旧值相同也会执行。
          • 然后return 一个React元素(描述组件,即UI),不负责组件实际渲染工作,之后由React自身根据此元素去渲染出页面DOM。render是纯函数(Pure function:函数的返回结果只依赖于它的参数;函数执行过程里面没有副作用。
          • 不能在里面执行this.setState,会有改变组件状态的副作用。
        3. componentDidMount(挂载完成)

          • 约定将ajax请求放在这个生命周期函数中
          • 组件挂载到DOM后被执行,只会执行一次。
    3. update (组件更新时)
      • 首先我们来了解一下什么时组件更新。只有在通过setState函数使sate和props变化或重新赋值时才叫组件更新。

      • setState引起父组件的render函数执行,同时也会引起它的子组件的render函数执行。

      • 原因是react虚拟DOM的diff算法,同级比较原理。

      • 只要重新赋值就是组件更新,如果值并没有变,也更新组件,这样就会耗性能,也是我们讲同级比较的时候说的一个弊端。

      • 接下来我们了解一下有那些周期函数

        1. componentWillReceiveProps(nextProps)

          • 此方法只调用于props引起的组件更新过程中,参数nextProps是父组件传给当前组件的新props。但父组件render方法的调用不能保证重传给当前组件的props是有变化的,所以在此方法中根据nextProps和this.props来查明重传的props是否改变,以及如果改变了要执行啥,比如根据新的props调用this.setState出发当前组件的重新render
        2. shouldComponentUpdate(nextProps, nextState)

          • 此方法通过比较nextProps,nextState及当前组件的this.props,this.state,返回true时当前组件将继续执行更新过程,返回false则当前组件更新停止,以此可用来减少组件的不必要渲染,优化组件性能。ps:这边也可以看出,就算componentWillReceiveProps()中执行了this.setState,更新了state,但在render前(如shouldComponentUpdate,componentWillUpdate),this.state依然指向更新前的state,不然nextState及当前组件的this.state的对比就一直是true了。
        3. componentWillUpdate(nextProps, nextState)

          • 此方法在调用render方法前执行,在这边可执行一些组件更新发生前的工作,一般较少用。
        4. render

          • render方法在上文讲过,这边只是重新调用。
        5. componentDidUpdate(prevProps, prevState)

          • 此方法在组件更新后被调用,可以操作组件更新的DOM,prevProps和prevState这两个参数指的是组件更新前的props和state
    • 优化弊端
    • 1.当因为父组件重新render,使得props重新被赋值,导致子组件跟着渲染.
    /**
     * 方法一:解决上述弊端,可以在shouldComponentUpdate函数,组件更新前进行判断,props是否改变,再确定是否执行重新渲染。
    */
    class Child extends Component {
       shouldComponentUpdate(nextProps){ 
            if(nextProps.value === this.props.value){
              return false
            }
            return true
        }
        render() {
            return <div>{this.props.value}</div>
        }
    }
    /**
     * 方法二:
     * 1.解决上述弊端,也可以先将this.props.value赋值给子组件的state
     * 2.再在componentWillReceiveProps函数中,使用setState去重新给stae中的属性赋值this.props.value
     * 3.文档中提到,在该函数(componentWillReceiveProps)中调用 this.setState() 将不会引起第二次渲染。
     * 4.因为componentWillReceiveProps是在props有变化的时候才会触发,所以在这里面做this.setState()一定是有改变state
    */
    //
    class Child extends Component {
        constructor(props) {
            super(props);
            this.state = {
                value: props.value // 先将this.props.value赋值给子组件的state
            };
        }
        componentWillReceiveProps(nextProps) { // 在props有变化的时候才会触发这个方法
            this.setState({value: nextProps.value}); // 重新赋值,引起render
        }
        render() {
            return <div>{this.state.value}</div>
        }
    }
    
    • 2.组件本身调用setState方法,但是并没有改变state中的值。
    /**
     * 也是通过shouldComponentUpdate判断新旧值是否改变,改变才做render
    */
    class Test extends Component {
       constructor(props) {
            super(props);
            this.state = {
              value:1
            }
       }
       shouldComponentUpdate(nextState){ // 应该使用这个方法判断新旧值是否改变
            if(nextState.value === this.state.value){
              return false // 没有改变返回false
            }
            return true
        }
    
       changeState = () => { // 虽然调用了setState ,但state并无变化
            const value = this.state.value
             this.setState({
                value
             })
       }
    
        render() {
            return <div onClick = {this.changeState}>{this.state.value}</div>
        }
    }
    
    
    1. 卸载阶段(componentWillUnmount)
    • 只有一个生命周期方法componentWillUnmount
      • 此方法在组件被卸载前调用,可以在这里执行一些清理工作,比如清楚组件中使用的定时器,清楚componentDidMount中手动创建的DOM元素等,以避免引起内存泄漏。
    1. 在react组件中,除了render函数,其他任何生命周期函数都可以不写,因为组件继承了react中的 Component,Component内置了其他的生命周期函数
  • 相关阅读:
    03 python学习笔记-文件操作
    02 Python学习笔记-基本数据类型
    01 Python简介、环境搭建及包管理
    一、如何使用postman做接口测试笔记一
    django测试开发-1.开始Hello django!
    Oracle创建用户并给用户授权查询指定表或视图的权限
    ORA-00933 UNION 与 ORDER BY
    excel设置单元格不可编辑
    oracle之分组内的字符串连接
    10 款强大的JavaScript图表图形插件推荐
  • 原文地址:https://www.cnblogs.com/boye-1990/p/11453735.html
Copyright © 2020-2023  润新知