sisterAn / JavaScript-Algorithms

基础理论+JS框架应用+实践,从0到1构建整个前端算法体系
5.45k stars 626 forks source link

react16新增了哪些生命周期、有什么作用,为什么去掉某些15的生命周期 #153

Open sisterAn opened 3 years ago

sisterAn commented 3 years ago
V16.3 之前

我们可以将生命周期分为三个阶段:

分开来讲:

  1. 挂载阶段
    • constructor:避免将 props 的值复制给 state
    • componentWillMount
    • render:react 最重要的步骤,创建虚拟 dom,进行 diff 算法,更新 dom 树都在此进行
    • componentDidMount
  2. 组件更新阶段
    • componentWillReceiveProps
    • shouldComponentUpdate
    • componentWillUpdate
    • render
    • componentDidUpdate
  3. 卸载阶段
    • componentWillUnMount

这种生命周期会存在一个问题,那就是当更新复杂组件的最上层组件时,调用栈会很长,如果在进行复杂的操作时,就可能长时间阻塞主线程,带来不好的用户体验,Fiber 就是为了解决该问题而生。

V16.3 之后

Fiber 本质上是一个虚拟的堆栈帧,新的调度器会按照优先级自由调度这些帧,从而将之前的同步渲染改成了异步渲染,在不影响体验的情况下去分段计算更新。

对于异步渲染,分为两阶段:

其中,reconciliation 阶段是可以被打断的,所以 reconcilation 阶段执行的函数就会出现多次调用的情况,显然,这是不合理的。

所以 V16.3 引入了新的 API 来解决这个问题:

  1. static getDerivedStateFromProps: 该函数在挂载阶段和组件更新阶段都会执行,即每次获取新的propsstate 之后都会被执行在挂载阶段用来代替componentWillMount;在组件更新阶段配合 componentDidUpdate,可以覆盖 componentWillReceiveProps 的所有用法。

    同时它是一个静态函数,所以函数体内不能访问 this,会根据 nextPropsprevState 计算出预期的状态改变,返回结果会被送给 setState返回 null 则说明不需要更新 state,并且这个返回是必须的

  2. getSnapshotBeforeUpdate: 该函数会在 render 之后, DOM 更新前被调用,用于读取最新的 DOM 数据。

    返回一个值,作为 componentDidUpdate 的第三个参数;配合 componentDidUpdate, 可以覆盖componentWillUpdate 的所有用法。

注意:V16.3 中只用在组件挂载或组件 props 更新过程才会调用,即如果是因为自身 setState 引发或者forceUpdate 引发,而不是由父组件引发的话,那么static getDerivedStateFromProps也不会被调用,在 V16.4 中更正为都调用。

即更新后的生命周期为:

  1. 挂载阶段
    • constructor
    • static getDerivedStateFromProps
    • render
    • componentDidMount
  2. 更新阶段
    • static getDerivedStateFromProps
    • shouldComponentUpdate
    • render
    • getSnapshotBeforeUpdate
    • componentDidUpdate
  3. 卸载阶段
    • componentWillUnmount

更多请看 深入 React 生命周期

fangyinghua commented 3 years ago

16.3 之后 这个 生命周期 没有了吧 componentWillMount