React 学习之再探生命周期

256 阅读4分钟

简介

不论是 React 还是 Vue,组件的 生命周期 都是不可忽略的一个知识点,我们可以通过在组件的生命周期中提供一系列的钩子函数(类似于事件)中注入相关操作的代码,然后在我们预期的时机去做一些事情。

简单定义:组件从诞生到销毁所经历一系列过程,我们就称为生命周期。

React 中,hooks 出现之前,生命周期仅存在与 类组件 中,函数组件每次调用都是重新运行函数,旧的组件即刻被销毁

React 16.x 版本是生命周期变更的一个转折点,我看到大多数文章都是说的 v16.3 版本引入了两个新的生命周期钩子函数 getDerivedStateFromPropsgetSnapshotBeforeUpdate,并在其未来版本中移除三个生命周期函数 componentWillMountcomponentWillReceivePropscomponentWillUpdate,所以想着自己来总结一下新旧生命周期的对比。

旧版生命周期

如下图所示

旧版生命周期示意图

创建组件阶段

  1. constructor (组件初始化)

    • 同一个组件对象只会执行一次
    • 不能在第一次挂载到页面之前,调用 setState 去更改状态值
  2. componentWillMount (组件即将被挂载)

    • 正常情况下,同 constructor 一样,只会运行一次 (可能在挂载前打断其生命周期,导致多次运行此生命周期函数;或者由于 ssr 方案会在服务端与客户端均会运行此生命周期函数)
    • 可以使用 setState,但为了避免 bug,一般不在此阶段更改状态值
  3. render (生成虚拟 DOM)

    • 返回虚拟 DOM,会被挂载到虚拟 DOM 树中,最终渲染到页面上
    • 只要需要重新渲染,render 方法就会被调用
    • 禁止 调用 setState,会导致无限递归渲染
  4. componentDidMount (组件已经挂载到页面上后)

    • 只会执行一次
    • 通常用于远程获取数据、开启计时器等相关操作

组件更新阶段

  1. componentWillResiveProps(nextProps) (属性变更触发) 基本无用

    • this.props 还是之前的属性,参数传递的就是新的属性值
  2. shouldComponentUpdate(nextProps, nextState) (返回值为布尔值,决定组件是否应该重新渲染)

    • 一般通过对比 this.propsnextPropsthis.statenextState 来决定此组件是否需要重新渲染
    • 此函数默认返回 true
    • React 内部封装的 PureComponent 应该就是在此生命周期做了对比封装
  3. render

  4. componentWillUpdate(nextProps, nextState) (组件即将被重新渲染)

  5. componentDidUpdate(prevProps, prevState) (组件已被重新渲染)

    • 一般可以用来回退之前的状态或操作 DOM

组件销毁阶段

componentWillUnmount (组件从虚拟 DOM 树中被移除时触发)

  • 通常在此函数中销毁一些依赖资源,比如:计时器,手动添加的事件监听等

新版生命周期

如下图所示

新版生命周期示意图

组件初始化到初次挂载阶段

  1. constructor (组件初始化)

    • 同一个组件对象只会执行一次
    • 不能在第一次挂载到页面之前,调用 setState 去更改状态值
  2. static getDerivedStateFromProps(props, state) → 移除旧版 componentWillMount

    • 静态方法,不能使用 this (this 指向构造函数本身),就 无法 获取当前的状态,或者调用 setState 更新状态
    • 两个参数分别是 新的属性新的状态
    • 函数返回 null 则表示不改变当前状态
    • 函数返回一个对象,则会像调用 setState 一样混合到组件状态之中
  3. render (生成虚拟 DOM)

    • 返回虚拟 DOM,会被挂载到虚拟 DOM 树中,最终渲染到页面上
    • 只要需要重新渲染,render 方法就会被调用
    • 禁止 调用 setState,会导致无限递归渲染
  4. componentDidMount (组件已经挂载到页面上后)

    • 只会执行一次
    • 通常用于远程获取数据、开启计时器等相关操作

组件更新阶段

  1. static getDerivedStateFromProps(props, state) (属性 / 状态 变更均会触发) 说明同上

  2. shouldComponentUpdate(nextProps, nextState) (返回值为布尔值,决定组件是否应该重新渲染)

    • 一般通过对比 this.propsnextPropsthis.statenextState 来决定此组件是否需要重新渲染
    • 此函数默认返回 true
    • React 内部封装的 PureComponent 应该就是在此生命周期做了对比封装
  3. render 说明同上

  4. getSnapshotBeforeUpdate(prevProps, prevState) (组件即将被重新渲染)

    • 真实 DOM 构建完成,但还未实际渲染到页面中
    • 两个参数分别是 之前的属性之前的状态
    • 在该函数中,通常用于实现需要手动控制的 DOM 的操作
    • 需要与 componentDidUpdate 钩子函数联合使用,否则会报警告
    • 返回值会作为 componentDidUpdate 的第三个参数,且需要显示返回一个值,否则会报警告
  5. componentDidUpdate(prevProps, prevState) (组件已被重新渲染)

    • 一般可以用来回退之前的状态或操作 DOM

组件销毁阶段

componentWillUnmount (组件从虚拟 DOM 树中被移除时触发)

  • 通常在此函数中销毁一些依赖资源,比如:计时器,手动添加的事件监听等

小结

以上便是本人对新旧生命周期钩子函数及相关简单使用说明的小结