【深入理解React】02_理解生命周期

前言

React16的生命周期相较于React 15有了改进,通过学习React 15和React 16的生命周期,来理解改进的意义。

React15 的生命周期

React的生命周期主要分为三个解读:挂载、更新和卸载。

在这里插入图片描述

挂载

当页面进行挂载时主要经历了:constructor -> componentWillMount -> render -> componentMount这个生命周期。

挂载过程在组件的一生中仅会发生一次,即该过程在生命周期中只会执行一次。这里涉及到钩子主要有:

  • constructor:可以对this.state进行初始化;
  • componentWillMount:在这一阶段由于JSX被处理为虚拟DOM,所以此时获取不到DOM节点,有些人喜欢在这里进行一些初始化的操作,然而会伴随危险;
  • componentDidMount:此时DOM已经被挂载在页面中,所以可以操作DOM,类似于异步请求、初始化操作也可以放在这里。

更新

React中的更新有两种,一种是由父组件更新触发的更新,一种是组件自身调用自己的setState触发的更新

父组件更新触发的更新的生命周期为:componentWillRecevieProps -> shouldComponentUpdate -> componentWillUpdate -> render -> componentDidUpdate

组件组我更新时的生命周期为:shouldComponentUpdate -> componentWillUpdate -> render -> componentDidUpdate

两者的区别在于由于没有触发componentWillRecevieProps

这里主要涉及到的钩子有:

  • componentWillReceviceProps:当父组件进行更新时,就会触发该声明周期。如果父组件导致组件重新渲染,即使props没有更改,也会调用此方法,如果只想处理更改,请确保进行当前值与变更值的比较;
  • shouldComponentUpdate:在更新之前,可以在这个函数内部返回ture||false来决定组件是否重新渲染子组件(类似pureComponent);
  • componentWillUpdate:在render之前被触发,此时你不可以在这里涉及一些真实的DOM操作,毕竟此时真实的DOM还没有在挂载;
  • componentDidUpdate:在render之后被触发,意味着更新完成,这时候你可以处理DOM了。

卸载

组件销毁的时候会触发该方法,而组件销毁有两种原因:一种是组件在父组件中被移除了;一种是组件设置了key,父组件在render的过程中,发现key的值和上一次不一致,那么这个组件就会被销毁。

这里涉及到的钩子是:

  • componentWillUnmount

React16 的生命周期

在这里插入图片描述

挂载

当页面进行挂载时主要经历了:constructor -> getDerivedStateFromProps -> render -> componentMount这个生命周期。

React16中废弃了componentWillMount,使用了getDerivedStateFromProps,它不是前者的替代品,毕竟作用不一样。getDerivedStateProps仅用来使用props来派生/更新state

static getDeriviedStateFromProps(props, state)
  • 由于这是一个静态方法,所以获取不到this;
  • 该方法接受父组件传递进来的props和当前组件自身的state
  • 需要以对象格式的返回值

更新

父组件更新触发的更新的生命周期为:getDerivedStateFromProps -> shouldComponentUpdate -> render -> getSnapshotBeforeUpdate -> componentDidUpdate

组件组我更新时的生命周期为:shouldComponentUpdate -> render -> getSnapshotBeforeUpdate -> componentDidUpdate

由此可见,React 16中更新了两点:

  • 移除了componentWillReviceProps,使用了getDrivedStateFromProps。由上面可知getDerivedStateFromProps不能操作this,只完成props派生/更新state,比起componentWillRevice能做的事情少了很多,即使用了减法,减少了副作用(如修改state、使用fecth获取数据等操作)。
  • 移除了componentWillUpdate,使用了getSnapshotBeforeUpdategetSnapshotBeforeUpdate的返回值会作为第三个参数传递给componentDidUpdate,它的执行机制是在render之后,真实DOM更新前,在这里可以获取到更新前的真实DOM,和更新前后的state/props

卸载

React 16的卸载过程与React 15一致。

Fiber

Fiber是React 16对React核心算法的一次重写,它会使原本同步的渲染过程变成异步的

在React 16之前,React的渲染模式是同步的,每次更新的时候,对比两个虚拟DOM,然后进行更新,这个更新过程是递归的过程。同步渲染的递归栈是特别深的,只有最底层的渲染返回了,才会逐层返回,由于主线程被占有用,无法做其他事情,这个漫长且不可打断的过程会导致页面白屏、卡顿等严重问题,

React 16之后,将渲染模式调整为异步模式,将渲染任务拆分为多个小任务,当一个小任务完成之后,交会主线程,可以指定下一个优先级较高的任务进行渲染,渲染过程中可以被打断。

为什么要改进生命周期

Fiber的主要特征就是可以异步渲染,实现这一目标却决与渲染过程中是否能被打断。

React 16的声明周期被划分为rendercommit(含pre-commit)两个阶段:

在这里插入图片描述

  • render阶段:是纯净的且没有副作用,可以被React暂停、终止或者重启;
  • pre-commit:可以读取真实的DOM;
  • commit:可以使用DOM,运行副作用,安排更新。

render阶段在执行过程中运行被打断,而commit阶段总是同步执行的。(render用户不可见,所以可以被打断,但是commit是可以操作DOM,是可见的,所以是同步的)。

React 16废弃了的componentWillMount、componentWillUpdate、componentWillReviceProps都处于render阶段,都可能被重复执行,而且这些API常年被滥用,会产生一系列的副作用:

  • 习惯在componentWillxxxx下的Fetch数据,这些完全可以转移到componentDidXXX中去做,异步请求再快也快不过同步的生命周期,首次渲染依然会在数据返回之前执行;
  • render阶段里的生命周期可以被重复执行,在componentWillXXX被打断+重启多次后可能会发起多个付款请求。

React 16改造生命周期的主要动机就是为了配合Fiber架构带来的异步渲染机制。

总结

  • React 16废弃了componentWillMount、componentWillReviceProps、componentWillUpdate,引入了getDerivedStateFromStategetSnapshotBeforeUpdate;
  • React 16中,挂载的生命周期为:constructor -> getDerivedStateFromProp -> render -> componentDidMount;
  • React 更新的生命周期触发条件由两种,一种是父组件更新,一种是子组件自身调用setState进行更新,前者的生命周期为:getDerviedStateFromState -> shouldComponentUpdate -> render -> getSnapshotBeforeUpdate -> componentDidUpdate,后者的生命周期为:shoundComponentUpdate -> render -> getSnapshotBeforeUpdate -> componentDidUpdate
  • React的卸载阶段会执行componentWillUnmount
  • getDerviedStateFromPropsgetSnapshotBeforeUpdate都是静态方法,所以不能使用this,可以避免骚操作,前者在render之前执行,后者在redner之后执行,可以操作更新前真实的DOM和更新前后的state/prop
  • Fiber是React 对Reacte核心算法的重新,主要将同步渲染改为异步渲染,提高渲染效率;
  • 渲染阶段分为render阶段、commit阶段,render对用户不可见,所以是异步的,commint可以获取真实的DOM,对用户可见,是同步的;
  • constructor、getDerivedStateFromProps、render、shouldCompoent属于render阶段,可以被暂停、终止和重启,getSnapshotBeforeUpdate属于pre-commit,这里可以获得DOM,componentDidMount、componentDidUpdate和componentWillUnmount属于commit阶段;
  • componentWillMount、componentWillReviceProps和componentDidUpdate由于长期被滥用,可能会创建一些副作用,且位于render阶段,无法避免若重复执行带来的危害性,为了配合Fiber架构,所以React 16对这三个钩子进行了移除。

参考

深入浅出搞定 React


如有错误,欢迎指出,感谢~

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值