顾名思义:组件的生命周期函数就是贯穿一个组件从出生(挂载)到死亡(卸载)这段时间中 特殊时间点所会触发的函数
一、生命周期执行顺序
(1)、挂载:
componentWillMount() ——> render() ——> componentDidMount()
(2)、更新
1、props更新,父级组件重新渲染
componentWillReceiveProps(nextProps) ——> shouldComponentUpdata(nextProps, nextState) 或
componentWillReceiveProps(nextProps) ——> shouldComponentUpdata(nextProps, nextState) ——> componentWillUpdate(nextProps, nextState) ——> render() ——> componentDidUpdate(prevProps, prevState)
2、state更新,自身状态发生改变
shouldComponentUpdate(nextProps, nextState) 或
shouldComponentUpdate(nextProps, nextState) ——> componentWillUpdate(nextProps, nextState) ——> render() ——> componentDidUpdate()
(3)、卸载
componentWillUnmount()
二、生命周期函数使用场景
(1)componentWillMount()
组件挂载阶段,render执行前执行。可以根据props进行setState,render会感知到更新后的state,仅会执行一次,不会触发重新渲染。
这里不建议发送AJAX请求,由于请求是异步的,在接下来的第一次render中,一定获取不到响应数据。
(2) render()
该方法创建一个虚拟dom,表示组件的输出。(输出可以应用到react-dom,react-native)
(3)componentDidMount()
组件挂载完毕,已经生成真实DOM。
可以对DOM节点进行操作,设置定时器,发送AJAX请求
(4) componentWillReceiveProps(nextProps)
已挂载组件在接收到新的props时会触发,这里的新的props有点歧义,可以理解为只要父组件重新渲染,子组件就会接收到新的props,从而触发这个方法。
当props发生变化,组件自身状态需要做出改变,即state做出对应响应时,可以在此方法中执行;
(5)shouldComponentUpdate(nextProps, nextState)
接收到新的props或state,判断是否需要发生重新渲染,默认返回true,表示重新渲染
该方法在首次渲染或者forceUpdate时不会触发
(6)componentWillUpdate(nextProps, nextState)
该方法中禁止调用this.setState()方法
使用该方法做一些更新之前的准备工作
(7)componentDidUpdate(prevProps, prevState)
在组件的更新已经同步到dom上立即调用,可以操作更新之后的dom
(8)componentWillUnmount()
在组件卸载之前调用,一般进行清除定时器,取消请求或清除在componentDidMount中创建的DOM元素等操作
三、React v16.3之后的生命周期
首先说一下React同步更新导致的性能问题:
组件更新需要耗费时间,当存在多重组件嵌套时,最顶部的父级组件更新导致下级的组件也要更新时,会占据大量的时间。浏览器的GPU在这段时间内只能进行更新工作,没办法做其他的事情,此时用户也无法与其进行交互,造成浏览器卡顿的现象。
解决方案:分片更新
React Fiber将更新过程碎片化,每执行一段更新过程,就把控制权交换给React负责任务协调的模块,看看是否有其他更紧急的任务要做,如果没有就继续更新,如果有紧急任务,就执行紧急任务,执行完毕之后从头开始进行更新任务。
更新过程:以render为界分为两个阶段,Reconciliation Phase(调和) 和 Commit Phase(重构)
第一个过程会找出需要更新哪些DOM,该过程可以被打断;
第二个阶段会把需要更新的DOM进行更新操作,不可打断
第一阶段可能会执行以下生命周期函数:componentWillMount、componentWillReceiveProps、shouldComponentUpdate、componentWillUpdate
第二个阶段:componentDidMount、componentDidUpdate、componentWillUnmount
第一阶段的生命周期函数在16.3由于采用分片更新可能会出现调用多次的情况,故废弃了componentWillReceiveProps、componentWillMount、componentWillUpdate,用getDerivedStateFromProps替代,目的在于强制开发者在render之前只做无副作用的操作。而且所作的操作也仅限于根据nextProps和nextState设置state。
getDerivedStateFromProps(nextProps, nextState)是一个静态函数,内部不能访问this。根据nextProps和nextState计算出预期的状态改变,返回结果会被送给setState
getSnapshotBeforeUpdate() 在render之后,componentDidUpdate之前执行
故16.3之后的挂载、更新和卸载执行顺序为:
挂载:getDerivedStateFromProps(nextProps, nextState) ——> render() ——> componentDidMount()
更新:
props更新:getDerivedStateFromProps(nextProps, nextState) ——> shouldComponentUpdate(nextProps, nextState)——> render——> getSnapshotBeforeUpdate(prevProps, prevState)——> componentDidUpdate(prevProps, prevState, snapShot);
state更新:shouldComponentUpdate(nextProps, nextState)——> render——> getSnapshotBeforeUpdate(prevProps, prevState)——> componentDidUpdate(prevProps, prevState, snapShot);
卸载: componentWillUnmount()
引用:https://moeover.com/2017/01/17/understand-react-lifecycle.html
https://wiki.jikexueyuan.com/project/react/component-specs-lifecycle.html