生命周期:组件从诞生到销毁会经历一系列的过程,该过程就叫做声明周期。React在组件的声明周期中提供了一系列的钩子函数(类似于事件),可以让开发者在函数中注入代码,这些代码会在适当的时候运行。

生命周期仅存在于类组件中,函数组件每次调用都是重新运行函数,旧的组件即刻被销毁

旧版生命周期

React < 16.0.0 . 官方已经不推荐使用旧版了,因为有一些问题不能解决。但我们仍要学习
image.png卸载是unmount
一、constructor:初始化阶段

  1. 同一个组件对象,只会创建一次,因此该函数只会运行一次
  2. 不能在组件第一次挂载到页面之前调用setState,为了避免问题,构造函数中严禁使用setState

二、componentWillMount:组件即将挂载到页面上

  1. 正常情况下,和构造函数一样,它只会运行一次
  2. 可以使用setState,但是为了避免bug,不要在这里使用。因为在某些特殊情况下,该函数可能被调用多次(比如:服务端ssr、以及在初始化阶段可能会把生命周期打断导致cwm等重新运行)

三、render

  1. 返回一个虚拟DOM,会被挂载到虚拟DOM中,它最终会被渲染到页面的真实DOM中
  2. render可能不止运行一次,只需要重新渲染,就会重新运行
  3. 严禁在render中调用setState(因为可能会导致无限递归渲染)

四、componentDidMount:在它调用之前,虚拟DOM已经成为真实DOM且挂载到页面中了

  1. 只会执行一次
  2. 可以使用setState
  3. 通常情况下,会将网络请求,启动计时器等一开始需要的操作,书写到该函数中

五、至此,组件完成挂载阶段,进入活跃状态,开始等待(等什么呢?等需要重新渲染的时候—>属性/状态变化)

六、componentWillRecieveProps:属性发生变化(指的是属性重新被赋值,内容不一定变)时就会触发该函数

  1. 即将接受新的属性值
  2. 参数为新的属性对象
  3. 该函数可能会导致一些bug,新版已移除,故不推荐使用

七、shouldComponentUpdate:状态发生变化或者cwrp完成后会触发该钩子函数,是一个性能优化点

  1. 指示React是否要重新渲染该组件,通过返回true或false来指定
  2. 默认情况下会直接返回true(也就是不写该函数时)
  3. 该函数有两个参数,第一个是nextProps,第二个是nextState

    1. //性能优化
    2. if(this.props.n===nextProps.n && this.state.n===nextState.n){
    3. return false;
    4. }
  4. 如果指定始终返回false,则会导致状态与UI不一致,因为没有真正地去更新DOM

八、componentWillUpdate:组件即将被重新渲染(必须上一步scu返回的是true才会触发)

九、render:职责同上述render一致

十、componentDidUpdate:组件已经完成重新渲染,然后调用该函数

  1. 该函数第一个参数是之前的属性,第二个参数是之前的状态
  2. 往往在该函数中使用DOM操作,改变元素

十一、至此更新阶段完成

十二、componentWillUnmount:组件即将被卸载,组件从虚拟DOM中移除后触发(我猜测是这样的)?

  1. 通常在该函数中,销毁一些组件依赖的资源,比如计时器
  2. 在componentWillUnmount中setState是一定成功的,但由于组件即将被卸载,你的setState并不会再次触发组件的render函数,因此出现了state和render函数中不同步的问题。我在用react-navigation的goback的时候,发现之前的页面被重置的state并没有被同步过去

当组件从真实DOM树中移除时,该组件被销毁(销毁阶段)

新版生命周期

React >= 16.0.0
React官方认为:某个数据的来源必须是单一的,要让数据的拥有者改变数据

image.png这里卸载应是unmount,上面打错了

主要有下述不同,其他同旧版一致

移除了:

componentWillMount(因为可能调用多次,导致很多bug)
componentWillRecieveProps(反模式:它可能造成数据来源不单一,父亲儿子都可影响,这就会出现bug)componentWillUpdate(主要是因为没啥用,意义不大)

新增了:

一、static getDerivedStateFromProps(从属性中获取新的状态,其实绝大部分下用不到)

  1. 该函数几乎没啥用,就是为了告诉你坚决反对 componentWillRecieveProps
  2. 在constructor之后,props或state变化后,(首次渲染或更新的)render前,调用该函数
  3. 它调用完了:若是更新阶段,就会调用 shouldComponentUpdate ,再调用render;

若是首次渲染阶段,则会调用render

  1. 通过参数可以获取新的属性和当前状态(即nextProps, currentState)
  2. 该函数的返回值(必须写null or object)会覆盖掉组件状态,不写这个函数则默认返回null(应该是这样)
  3. 该函数是静态的

二、getSnapshotBeforeUpdate(获取更新前的快照)

  1. 处于更新流程时 且 在render之后,componentDidUpdate之前调用该函数
  2. 执行时机:真实的DOM构建完成,但还未实际渲染到页面中(因为JS主线程与UI线程互斥)
  3. 在该函数中,通常用于实现一些附加到DOM操作—比如滚动条效果等
  4. 通过参数可以获取更新前的属性和状态,第一个参数是prevProps,第二个参数是prevState
  5. 该函数的返回值(必须是有效的值)会作为 componentDidUpdate 的第三个参数