react生命周期

16.3版本之前的生命周期

生命周期一共费为四个阶段:initialization(组件初始化阶段),mounting(组件挂载阶段),update(组件更新阶段),unMounting(组件卸载阶段)。

initialization(组件初始化阶段)
import React, { Component } from 'react';
class SetWord extends Component {
    constructor(props){
        super(props)
    }

    render() {
        ...
    }
}
export default SetWord

在组件的初始化阶段,创建的类继承react component这个基类,这样才可以使用render,生命周期等方法。这里也反映出了为什么函数组件中不能使用这些方法的原因。

当我们没有显式的写constructor,程序自己增加一个空的constructor,如果我们显式的写了之后就必须调用super()

super()函数是用来调用基类的constructor()的,将父组件的props注入给子组件。供子组件读取(只读)。

mounting(组件挂载阶段)
  • componentWillMount
    • 组件挂载到DOM前调用
    • 只会被调用一次
    • 在这个生命周期中setState不会引起组件重新渲染
    • 可以调用setStat,但是没啥用,不会触发渲染
  • render
    • 当组件的state和props变化的时候就会触发render方法
    • return一个react元素,不负责渲染工作,之后react自身根据此元素去渲染页面
    • render是纯函数(函数的返回结果只依赖于他的传入结果,函数执行过程中没有副作用)
    • 在render中不能使用setState(),会改变组件状态的副作用,并且会造成死循环栈溢出
    • render不能返回undefined
  • componentDidMount
    • 组件挂载到DOM之后调用,并且只执行一次
    • 数据初始化和添加订阅事件的工作可以在这进行
    • 可以调用setState
update(组件的更新阶段)

react更新机制:setState引起state更新,父组件引起props更新,更新之后无论state和props有没有变化,都会引起子组件的重新render

  • componentWillReceiveProps(nextProps)
    • 当props更新的时候,这个生命周期会被触发。这也是props变化之后进行更新数据的唯一方,参数nextProps是父组件传递过来新的props数据
    • 但是父组件render方法的调用不能保证nextProps的数据和之前是有变化的。所以在这个方法中可以对props进行对比
    • 在componentWillReceiveProps中可以将props转化成子组件自己的state,并且在这里setState不会引起二次渲染。
    • 可以调用setState
  • shouldComponentUpdate(nextProps,nextState)
    • 当props和state更新的时候会触发这个生命周期
    • 在这个生命周期中有两个参数:nextProps和nextState,nextProps是传递Props的更新,nextState传递的是state的更新。
    • 在这个生命周期中我们可以通过比对nextProps和this.props,nextState和this.state,来判断页面需不需要render
    • 当componentWillReceiveProps中执行了setState()更新了state,但是在render之前this.state依然指向更新前的state。
    • 这个生命周期中必须有返回值,返回值类型是boolean,返回true则代表渲染(当返回true的时候,react元素回进行比对,然后来判断是否要render某一模块),返回false则代表不渲染(返回false则不会进行比对)
    • 注意:这个生命周期虽然可以进行性能优化,但是远远没有那么优秀
      • 添加shouldComponentUpdate方法一般都会拖慢组件的更新速度
        • 这是为什么呢?显然当我们使用shouldComponentUpdate的时候,会有一些比对的操作,当props很大的时候,这个比对的操作可能不会很快。
        • 而且react diff算法 自己对于什么时候更新,更新什么,有自己一套很好的逻辑。所以我们自己来做大程度上回画蛇添足。
      • 使用shouldComponentUpdate对于我们的性能提升可能也是微乎其微的。
      • 使用shouldComponentUpdate的时候,可能会引起一些不易察觉的bug,
    • 所以综上:我们使用shouldComponentUpdate的时候,确实会对自己页面有真实显著的提升的时候可以使用,如果微乎其微,则没有必要使用。
    • 可以使组件继承react.PureComponent,这个时候当props和state更新的时候可以有一个浅比较
  • componentWillUpdate(prevProps, prevState)
    • 执行一些组件更新前的操作。
    • 使用率不高
    • 不能调用setState,会造成重复循环
  • render
    • 调用渲染页面,和挂载阶段的流程一样。
  • componentDidUpdate(prevProps, prevState)
    • 此方法在组件更新之后调用,可以操作dom,
    • 参数prevProps和prevState代表的时候组件更新之前的props和state
    • 适合请求接口数据
    • setState,可能回触发重复渲染。需要自己判断
unMounting(卸载阶段)
  • componentWillUnMount
    • 在组件卸载之前调用
    • 在这执行一些清理工作,比如结束定时器,绑定的事件什么的,操作避免内存泄漏

16.4+版本生命周期

当16.0+版本中推出fiber之后,旧版的生命周期就不适合了。当开启async rendering,在render之前的所有函数都有可能被执行多次。这也意味着这些函数中的操作也要被执行多次。

render之前的生命周期除了shouldComponentUpdate,其他的全部都被getDerivedStateFromProps所替代

mounting(挂载阶段)
  • constructor

  • static getDerivedStateFromProps(nextProps, prevState)

    • 看名字就知道:从props中获取state,他的功能也是将父组件传递的props中的数据映射到当前组件state中
    • 无论是更新阶段还是挂载阶段, 都会调用getDerivedStateFromProps
    • 随着getDerivedStateFromProps的推出,老的生命周期被替代,这些被替代的生命周期目前还能用,但是在17版本中会被彻底废弃
      • componentWillReceiveProps
      • componentWillMount
      • componentUpdate
      • 之前在上面三个生命周期中写的逻辑可以都搬到getDerivedStateFromProps,但是要是没有副作用的,如果有副作用的就要挪到其他的生命周期中。
    • 使用之前要在前面加上static保留字,声明为静态方法,不然会被react忽略掉
    • getDerivedStateFromProps里面的this为undefined,static静态方法只能Class来调用,实例时不能实例化静态方法的。当调用React class组件时,该组件会实例化,所以react class组件中静态方法getDerivedStateFromProps无权访问class实例中的this,所以this为undefined
    • 每当父组件引发子组件渲染过程的时候会被调用,这样我们可以根据nextProps和prevState来调整state
    • 如果props传入的内容不要影响页面的渲染,那么就需要返回一个null
    • 使用场景
      • 当一个组件既受控,又自控的场景我们就需要注意:类似的这种情况是非常混乱的,如果要判断也是比较负责的,所以我们开发的时候尽量要避开这种情况,同一个数据要么是props驱动,要么是state驱动,如果是在没有办法解偶我们可以将props整个缓存在代码。然后通过判断新的数据和旧数据中的差异进行判断。
      • 最好的方式还是将props和state数据进行分离,将所有的组件分为展示型组件和容器型组件。一个只负责接受props改变样式,一个保持整个模块的state。但是在复杂的业务场景中很难做到这种的。
  • render

  • componentDidMount

update(更新阶段)
  • static getDerivedStateFromProps(props, state)
  • shouldComponentUpdate
  • render
  • getSnapshotBeforeUpdate
    • 看名字就能知道这个生命周期的作用:更新前获取快照
    • 这个周期执行的时候DOM还没有被更新,给了我们一个获取DOM信息的机会。计算得到一个snapshot,snapshot会作为componentDidUpdate的第三个参数传入。
    • 纵然这样,这个方法还是挺鸡肋的,你细品,好像没有多少场景可以用到这个方法。
    getSnapshotBeforeUpdate(prevProps,prevState){
        console.log(prevProps,prevState)
        return 'fanfan'
    }
    
    conponentDidUpdate(prevProps, prevState, snapshot){
        console.log(snapshot); // fanfan
    }
  • componentDidUpdate
unMounting(卸载时)
  • componentWillUnount

总结:新的生命周期最大的特点就是:使用getDerivedStateFromProps是为了强制让开发者在render之前只做无副作用的操作。并没局限于根据props和state决定新的state

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值