类组件

React 16.3 生命周期

  • getDerivedStateFromProps
  • componentWillMount ( 已被标记弃用)
  • getSnapshotBeforeUpdate (新增)
    这个生命周期的设计初衷,是为了“与 componentDidUpdate 一起,涵盖过时的 componentWillUpdate 的所有用例”(引用自 React 官网)。
  • componentDidMount
  • componentWillReceiveProps (已被标记弃用)
  • getDerivedStateFromProps
  • shouldComponentUpdate
  • componentWillUpdate (已被标记弃用,与后来的异步渲染不兼容)
  • componentDidUpdate
  • componentWillUnmount
    1.png

为什么要去除掉 componentWillUpdate

因为 react 15 是同步进行渲染,同步渲染的递归栈是非常深的,而且不能打断,这样就很容易一直占据着主线程,直到递归结束释放主线程**。在这个过程中,浏览器没有办法处理任何渲染之外的事情,会进入一种无法处理用户交互**的状态。因此若渲染时间稍微长一点,页面就会面临卡顿甚至卡死的风险。

React 更新策略 机制下,render 阶段是允许暂停、终止和重启的。当一个任务执行到一半被打断后,下一次渲染线程抢回主动权时,这个任务被重启的形式是“重复执行一遍整个任务”而非“接着上次执行到的那行代码往下走”。这就导致 render 阶段的生命周期都是有可能被重复执行的

我们再来看看 React 16 打算废弃的是哪些生命周期:

  • componentWillMount;
  • componentWillUpdate;
  • componentWillReceiveProps。

这些生命周期的共性,就是它们都处于 render 阶段,都可能重复被执行,而且由于这些 API 常年被滥用,它们在重复执行的过程中都存在着不可小觑的风险。

React 团队给出的这篇文章 就帮助大家规避“误操作”来说是绰绰有余的。

缺点

  • this 的模糊性;
  • 业务逻辑散落在生命周期中;
  • React 的组件代码缺乏标准的拆分方式。
  • 在类中难以做编译优化,React 团队一直在做前端编译层的优化工作,比如常数折叠(constant folding)、内联展开(inline expansion)及死码删除(Dead code elimination)等。
  • React 类组件内部预置了相当多的“现成的东西”等着你去调度/定制,state 和生命周期就是这些“现成东西”中的典型。要想得到这些东西,难度也不大,你只需要轻轻地继承一个 React.Component 即可。但是多就是好吗他增加了我们的学习成本,这时就显得类组件太重了。