react类组件生命周期基础总结

组件的生命周期是指组件从被创建到挂载到页面中运行起来,再到组件不用时卸载的过程,只有类组件才有生命周期(类组件 实例化  函数组件 不需要实例化)

 生命周期新版本和旧版本的对比图如下:

 生命周期(constructor())

类组件继承了react Component这个基类,也就继承这个react的基类,才能有render(),生命周期等方法可以使用,这也说明为什么函数组件不能使用这些方法的原因。

 constructor():它的入参是props(由父作用域传递过来的自定义属性和children[组件内部嵌套的视图结构]) 第一行代码必须是super(props),调用父类的构造器函数

  • 组件自有的state只能在这里定义(先定义后使用),state就是所谓的声明式变量
  • 在这里不能修改props,在这里也不能用props来做运算(因为constructor在声明周期中只发生一次)。
  • 在这里不要把props和state进行交叉赋值,在React代码逻辑中,永远要保持props和state的独立性。
  • 在这里不要使用this.setState来修改state。刚赋完值就进行render,而在constructor中,render生命周期都还没有生成。
  • 一般情况下,不要在这里写业务逻辑。有时候我们需要改变this指向时候唯一允许这么做,比如DOM、BOM操作等不要在这里做。
  • 一般继承父类、定义状态、改变this指向。

生命周期(挂载阶段)

钩子 函数

触发时机

作用

constructor

创建组件时,最先执行,初始化的时候只执行一次

1. 初始化state  

2. 创建 Ref 

3. 使用 bind 解决 this 指向问题等

render

每次组件渲染都会触发

渲染UI(注意: 不能在里面调用setState() )

componentDidMount

组件挂载(完成DOM渲染)后执行,初始化的时候执行一次,在浏览器更新视图之前调用

1. 发送网络请求   

2.DOM操作

componentWillMount():react 16.3之前

        在组件挂载到DOM前调用,且只会被调用一次,在这边调用this.setState不会引起组件重新渲染,也可以把写在这边的内容提前到constructor()中,所以项目中很少用。

componentDidMount():react 17之后

  • 相当于Vue中的mounted(),表示挂载阶段已完成,这个声明周期只执行一次。
  • 各种业务逻辑(DOM、ref、掉接口、开定时器等等都可以在这里做)
  • 在这里可以使用多次this.setState(),默认是异步的。
  • 这个声明周期是在更新阶段的,发生在render之后

 生命周期(更新阶段)

react 16.3之前

  • componentWillReceiveProps(nextProps,nextState)
    • 这个生命周期主要为我们提供对props发生改变的监听,如果你需要在props发生改变后,相应改变组件的一些state,在这个方法中改变state不会二次渲染,而是直接合并state。
  • shouldComponentUpdate(nextProps,nextState)
    • 会返回一个布尔值,判断是否需要更新渲染组件,返回false,不会再向下执行生命周期,是优化react应用的主要手段之一,在这个方法中不能调用setState(),会导致循环调用
  • componentWillUpdate
    • 这个生命周期用来处理Dom发生更新之前的事情,在这个阶段不可以调用setState,会导致循环调用
  • render
  • componentDidUpdate(preProps,preState)
    • 此时已经完成渲染,Dom和state都已经发生变化,参数都是上一个状态的值

react 17之后

  • getDerivedStateFromProps(nextProps,preState)
    • 可以返回一个对象用来更新state。
  • shouldComponentUpdate render getSnapshotBeforeUpdate(preProps,preState)
    • 在这个阶段可以拿到上一个状态Dom元素的坐标、大小等相关信息。用于替代旧的生命周期中的componentWillUpdate
  • componentDidUpdate的第三个参数出现。
    • 在最近一次渲染提交到DOM树之前执行,可以用来获取更新前的DOM信息。
  • componentDidUpdate(preProps,preState,snapshot)
    • 首次渲染不会调用,组件更新后立即调用,在这个生命周期中使用this.setState时必须将其包裹在条件语句中,否则会导致死循环。

更新阶段会在三种情况下触发:

1、父组件更改props:一个组件并不能主动更改它拥有的props属性,它的props属性是由它的父组件传递给它的。强制对props进行重新赋值会导致程序报错。

  • 直接使用,每当父组件重新render导致的重传props,子组件将直接跟着重新渲染,无论props是否有变化。可通过shouldComponentUpdate方法优化。
  • 在componentWillReceiveProps方法中,将props转换成自己的state

 2、更改state:state的更改是通过setState接口实现的。组件的更新原因很大一部分是因为调用setState接口更新state所致,我们常常以同步的方式调用setState,但实际上setState方法是异步的。

  • 组件本身调用setState,无论state有没有变化。可通过shouldComponentUpdate方法优化。

 3、调用forceUpdate方法:强制组件进行更新。

 生命周期(卸载阶段)

钩子 函数

触发时机

作用

componentWillUnmount

组件卸载(从页面中消失)

执行清理工作(比如:清理定时器等)

在新版本中,某些生命周期废弃原因: componentWillMount、componentWillReceiveProps、componentWillUpdate这三个生命周期钩子都是在render阶段执行的

(1)在fiber架构被应用之前,render阶段是不能被打断的,页面复杂以后,就有可能阻塞页面的渲染;

(2)于是react推出fiber架构,使原本同步的渲染过程变成异步的,将一个大的更新任务拆解成许多小任务,低优先级任务的render阶段可以被高优先级任务打断;

(3)这就导致在render阶段执行的生命周期函数会被多次调用,如果在这些函数中执行一些带有副作用的操作,比如发送网络请求,就会导致一个同样的网络请求被调用多次,因此需要一个新的生命周期去解决这个问题;

(4)用静态函数getDerivedStateFromProps来取代被废弃的几个生命周期函数,开发者就无法通过this获取到组件实例,也不能发送网络请求或调用this.setState,通过强制开发者在render之前只做无副作用的操作来避免对生命周期的滥用。

猜你喜欢

转载自blog.csdn.net/qq_43641110/article/details/130747242