组件挂载卸载过程

  • constructor
  • componentWillMount
  • render
  • componentDidMount
  • componentWillUnMount

render: 当父组件的 render 函数被运行时, 它的子组件的 render 函数也会被重新运行render函数, 会插入jsx生成的dom结构,react会生成一份虚拟dom树,在每一次组件更新时,在此react会通过其diff算法比较更新前后的新旧DOM树,比较以后,找到最小的有差异的DOM节点

componentDidMount: 组件第一次渲染完成,dom 节点已经生成。在这可进行网络请求,setState后组件会重新渲染。
componentWillUnMount: 组件卸载,数据销毁。在这里移除所有的定时器、监听等。
react 为什么要清除定时器setTimeout\setInterval?
所有的单页应用都应该主动清除。因为是单页应用,定时器是运行后是存在内存中的,即使切换路由,也还是在这个页面没有离开,所以还是会继续运行的。
为什么传统页面不需要清除呢?因为传统页面是多页的,点击一个链接不是跳转路由,而是打开一个新的页面,旧页面内存中的数据都被自动清除了。

组件更新过程

  • componentWillReceiveProps
  • shouldComponentUpdate
  • componentWillUpdate
  • render
  • componentDidUpdate

shouldComponentUpdate:

  • 主要用于性能优化(部分更新),因为react父组件的重新渲染会导致其所有子组件的重新渲染,这个时候其实我们是不需要所有子组件都跟着重新渲染的,因此需要在子组件的该生命周期中做判断
  • 唯一用于控制组件是否进行重新渲染的生命周期,在react中,setState以后,state发生变化,组件会进入重新渲染的流程,在这里return false可以阻止组件的更新, 以此可用来减少组件的不必要渲染,优化组件性能。


image.png


getDerivedStateFromProps(nextProps, prevState) 代替 **componentWillReceiveProps(nextProps)
componentWillReceiveProps(nextProps)方法判断前后两个 props 是否相同,如果不同再将新的 props 更新到相应的 state 上去。这样做一来会破坏 state 数据的单一数据源,导致组件状态变得不可预测,另一方面也会增加组件的重绘次数。
举个例子:

  1. // before
  2. componentWillReceiveProps(nextProps) {
  3. if (nextProps.isLogin !== this.props.isLogin) {
  4. this.setState({
  5. isLogin: nextProps.isLogin,
  6. });
  7. }
  8. if (nextProps.isLogin) {
  9. this.handleClose();
  10. }
  11. }
  12. // after
  13. static getDerivedStateFromProps(nextProps, prevState) {
  14. if (nextProps.isLogin !== prevState.isLogin) {
  15. return {
  16. isLogin: nextProps.isLogin,
  17. };
  18. }
  19. return null;
  20. }
  21. componentDidUpdate(prevProps, prevState) {
  22. if (!prevState.isLogin && this.props.isLogin) {
  23. this.handleClose();
  24. }
  25. }

这两者最大的不同就是:
在 componentWillReceiveProps 中,我们一般会做以下两件事,一是根据 props 来更新 state,二是触发一些回调,如动画或页面跳转等。
而在新版本中,官方将更新 state 与触发回调重新分配到了 getDerivedStateFromProps 和componentDidUpdate 中,使得组件整体的更新逻辑更为清晰。而且在 getDerivedStateFromProps 中还禁止了组件去访问 this.props,强制让开发者去比较 nextProps 与 prevState 中的值,以确保当开发者用到 getDerivedStateFromProps 这个生命周期函数时,就是在根据当前的 props 来更新组件的 state,而不是去做其他一些让组件自身状态变得更加不可预测的事情。

getSnapshotBeforeUpdate(prevProps, prevState)** 代替componentWillUpdate
常见的 componentWillUpdate 的用例是在组件更新前,读取当前某个 DOM 元素的状态,并在 componentDidUpdate 中进行相应的处理。
这两者的区别在于:
在 React 开启异步渲染模式后,在 render 阶段读取到的 DOM 元素状态并不总是和 commit 阶段相同,这就导致在 componentDidUpdate 中使用 componentWillUpdate 中读取到的 DOM 元素状态是不安全的,因为这时的值很有可能已经失效了。
getSnapshotBeforeUpdate 会在最终的 render 之前被调用,也就是说在 getSnapshotBeforeUpdate 中读取到的 DOM 元素状态是可以保证与 componentDidUpdate 中一致的。
此生命周期返回的任何值都将作为参数传递给componentDidUpdate()