react(踩坑五)

生命周期详解

  1. class组件和hooks生命周期的对比
    在这里插入图片描述
  2. 16版本后的生命周期

react16.4后使用了新的生命周期,使用
getDerivedStateFromProps(挂载阶段和组件更新阶段都会执行,也就是props和state更新后都会被执行)
代替了旧的componentWillReceiveProps(在这期间。可以访问props并且可以进行修改,state 数据的单一数据源)及componentWillMount。
getSnapshotBeforeUpdate(在 render 之后, DOM 更新前被调用,用于读取最新的 DOM 数据)
代替了旧的componentWillUpdate(异步渲染,获取到dom状态时可能已经失效)。在这里插入图片描述
3. 多个组件执行顺序
挂载阶段
父组件 getDerivedStateFromProps —> 同步子组件 getDerivedStateFromProps —> 同步子组件 componentDidMount —> 父组件 componentDidMount —> 异步子组件 getDerivedStateFromProps —> 异步子组件 componentDidMount
如果父组件中包含异步子组件,则会在父组件挂载完成后被创建。
第 一 阶段,由父组件开始执行到自身的 render,解析其下有哪些子组件需要渲染,并对其中 同步的子组件 进行创建,按 递归顺序 挨个执行各个子组件至 render,生成到父子组件对应的 Virtual DOM 树,并 commit 到 DOM。
第 二 阶段,此时 DOM 节点已经生成完毕,组件挂载完成,开始后续流程。先依次触发同步子组件各自的 componentDidMount,最后触发父组件的。

更新阶段(先子后父)
React 的设计遵循单向数据流模型 ,也就是说,数据均是由父组件流向子组件。

第 一 阶段,由父组件开始,执行

static getDerivedStateFromProps
shouldComponentUpdate

更新到自身的 render,解析其下有哪些子组件需要渲染,并对 子组件 进行创建,按 递归顺序 挨个执行各个子组件至 render,生成到父子组件对应的 Virtual DOM 树,并与已有的 Virtual DOM 树 比较,计算出 Virtual DOM 真正变化的部分 ,并只针对该部分进行的原生DOM操作。

第 二 阶段,此时 DOM 节点已经生成完毕,组件挂载完成,开始后续流程。先依次触发同步子组件以下函数,最后触发父组件的。

getSnapshotBeforeUpdate()
componentDidUpdate()

父组件 getDerivedStateFromProps —> 父组件 shouldComponentUpdate —> 子组件 getDerivedStateFromProps —> 子组件 shouldComponentUpdate —> 子组件 getSnapshotBeforeUpdate —> 父组件 getSnapshotBeforeUpdate —> 子组件 componentDidUpdate —> 父组件 componentDidUpdate

卸载阶段(先父后子)
componentWillUnmount(),顺序为 父组件的先执行,子组件按照在 JSX 中定义的顺序依次执行各自的方法。

注意 :如果卸载旧组件的同时伴随有新组件的创建,新组件会先被创建并执行完 render,然后卸载不需要的旧组件,最后新组件执行挂载完成的回调。

  1. 兄弟组件
    挂载阶段
    若是同步路由,它们的创建顺序和其在共同父组件中定义的先后顺序是 一致 的。

若是异步路由,它们的创建顺序和 js 加载完成的顺序一致。

更新阶段、卸载阶段
兄弟节点之间的通信主要是经过父组件(Redux 和 Context 也是通过改变父组件传递下来的 props 实现的),满足React 的设计遵循单向数据流模型, 因此任何两个组件之间的通信,本质上都可以归结为父子组件更新的情况 。

所以,兄弟组件更新、卸载阶段,请参考 父子组件。