React 生命周期
首先,拿一个例子来说明React的生命周期流程。
例子:
有一个名为Count的组件,展示当前的总和(初始为0),有一个按钮,每次点击按钮,数字加一,另外还有一个卸载按钮,点击将这个组件在页面中卸载。
代码如下:
class Count extends React.Component {
constructor(props) {
console.log("Count组件调用了constructor生命周期钩子");
super(props);
this.state = { count: 0 };
}
add = () => {
const { count } = this.state;
this.setState({ count: count + 1 });
};
// 组件渲染
render() {
console.log("Count组件调用了render生命周期钩子");
return (
<div>
<h1>当前的和为:{this.state.count}</h1>
<button onClick={this.add}>点我+1</button>
<button onClick={this.death}>卸载组件</button>
</div>
);
}
}
展示的效果如下:
旧版本
React中,组件有两种主要的流程,即挂载时、更新时。
挂载时,一个组件要经历初始化、预挂载、渲染到页面、挂载到页面后,这几个重要的时间点。
对应到代码中:
- 初始化:调用类中的构造器函数。
- 预挂载:即将把组件展示到页面上,在
React中是componentWillMount生命周期钩子。 - 渲染到页面:即组件的效果完全展示到页面上的过程,即
React组件的render生命周期钩子。 - 挂载到页面后:即组件的效果在页面中展示完毕后,在
React中是componentDidMount生命周期钩子。
在上面的例子中,我们可以把这些生命周期钩子全部写在组件中,在这些生命周期钩子中我们不做别的事情,仅仅输出一句话,表明调用了该生命周期钩子,按照以上代码已有生命周期钩子中的输出语句写。
最终运行效果:
更新时,根据引起更新的原因不同,分为三个更新流程起点。
三种更新的情况:
-
父组件引起子组件的更新
流程:
componentWillReveiveProps--->shouldComponentUpdate--->componentWillUpdate--->render--->componentDidUpdate -
调用
setState引起的更新:流程:
shouldComponentUpdate--->componentWillUpdate--->render--->componentDidUpdate -
调用
forceUpdate引起的更新流程:
componentWillUpdate--->render--->componentDidUpdate
componentWillReveiveProps:子组件接收到新的父组件更新的数据,除了第一次。
shouldComponentUpdate:组件是否应该更新,这个生命周期钩子像是一个阀门,它返回一个布尔值,true为打开阀门,允许组件更新,false为关闭阀门,不允许组价更新。
componentWillUpdate:组件将要更新,调用forceUpdate方法能够直接从该流程开始,越过了”阀门“,有强制更新组件的意思。
render:将新的组件渲染到页面上的过程。
componentDidUpdate:组件更新完毕后。
用上面同样的方法可以验证组件更新时的生命周期的执行流程。
附上流程图:
新版本
从React的17版本开始,官方废除了3个生命周期钩子,新增了2个生命周期钩子,废除的生命周期钩子仍然能够使用,但是控制台会出现警告,在17版本以后这些生命周期钩子必须加上UNSAFE_的前缀才能消除这些警告。
废除的生命周期钩子:
UNSAFE_componentWillMountUNSAFE_componentWillReceivePropsUNSAFE_componentWillUpdate
为什么要废除这些生命周期钩子?
首先UNSAFE前缀并不是说这些生命周期钩子不安全,而是React官方在未来会开发一种叫异步渲染的技术,而这之前很多开发者有滥用这些生命周期钩子的情况,而这种情况会在未来新开发的“异步渲染”的技术中会引起很多的问题,所以React官方在这几个生命周期钩子前增加了前缀,增加了开发者使用这些生命周期钩子的成本,在未来这几个生命周期钩子可能会被废除。
新增的生命周期钩子:
-
getDerivedStateFromProps使用方法:
static getDerivedStateFromProps(props, state)参数:
props:组件即将用来渲染的下一个props。state:组件即将渲染的下一个state。
如果你定义了
static getDerivedStateFromProps,React会在初始挂载和后续更新时调用render之前调用它。它应该返回一个对象来更新state,或者返回null就不更新任何内容。此方法适用于 少数罕见用例,其中
state取决于props随着时间的推移的变化。 -
getSnapshotBeforeUpdate使用方法:
getSnapshotBeforeUpdate(prevProps, prevState)参数:
prevProps:更新之前的Props。prevProps将会与this.props进行比较来确定发生了什么改变。prevState:更新之前的State。prevState将会与this.state进行比较来确定发生了什么改变。
如果你实现了
getSnapshotBeforeUpdate,React会在React更新DOM之前时直接调用它。它使你的组件能够在DOM发生更改之前捕获一些信息(例如滚动的位置)。此生命周期方法返回的任何值都将作为参数传递给componentDidUpdate。例如,你可以在像是需要在更新期间保留其滚动位置的聊天消息的
UI中来使用它。
新的生命周期流程图: