1、旧 的生命周期函数(9个)
-
初始化时调用的生命周期函数(初始化由 ReactDOM.render() 引发)
- constructor —— 就是类的构造器,最早执行的,一生只执行一次 。
- UNSAFE_componentWillMount —— 将要挂载,一生只执行一次。
旧名称为 componentWillMount ,已经废弃。在未来的某个新版本开始将不再支持旧名称的写法。
- render —— 将组件渲染到页面中,将执行至少一次。
- componentDidMount —— 组件挂载完毕后执行,常在该函数内做一些初始化的操作。
-
更新阶段会调用的生命周期函数(由组件内部的数据更新或父组件重新渲染时调用)
- UNSAFE_componentWillReceiveProps —— 当前组件的父组件只要触发 render 重新渲染时,子组件就会调用这个生命周期函数 。
旧名称为 componentWillReceiveProps ,已经废弃。在未来的某个新版本开始将不再支持旧名称的写法。
- shouldComponentUpdate —— 该函数有一个 boolean 类型的返回值,决定是否进行更新操作。若该函数返回 false,则再不会执行下方的三个函数。
该函数如果不自行指定的话,默认是返回一个true,继续更新操作的。若自行指定,则需要设定一个 boolean 类型的返回值,如果没有指定返回值,则返回一个 undefined,即 boolean 类型的 false,则不会接着执行更新的操作。
- UNSAFE_componentWillUpdate —— 即将更新,还没有更新。
旧名称为 componentWillUpdate ,已经废弃。在未来的某个新版本开始将不再支持旧名称的写法。
- render —— 走到这里,数据已经更新,准备重新渲染组件。
- componentDidUpdate —— 数据更新完毕,组件重新渲染完毕。
会接收到两个参数。分别是:旧的 props,旧的 state。(在新版生命周期中,新增了一个 getSnapshotBeforeUpdate 生命周期函数,会返回一个自定义的数据给 componentDidUpdate 作为第三个参数)
-
卸载组件时调用的声明周期函数(由 ReactDOM.unmountComponentAtNode() 方法触发)
- componentWillUnmount —— 即将卸载当前组件,可以执行一下收尾性的工作 。
下方代码简单演示除 UNSAFE_componentWillReceiveProps 生命周期函数之外所有的生命周期函数的相关内容。
class OldTotalExample extends React.Component{
// 构造器 组件挂载前调用一次,最早
constructor(props){
console.log('constructor');
super(props);
this.state = {
num:0
}
}
// 点击按钮进行自增的函数(自定义函数)
autoIncrement = ()=>{
this.setState({
num:this.state.num + 1
})
}
// 点击按钮将组件卸载 (自定义函数)
destroyComponent = ()=>{
// 手动卸载当前组件的函数
React.unmountComponentAtNode(document.getElementById('test'));
}
// 点击按钮强制更新组件 (自定义函数)
forceRefresh = () =>{
// 触发重新渲染
this.forceUpdate();
// 后续执行顺序 componentWillUpdate -> render -> componentDidUpdate
}
// 挂载前调用一次,一生中只调用一次
UNSAFE_componentWillMount(){
console.log('componentWillMount');
}
// 挂载完调用一次,一生只调用一次
componentDidMount(){
console.log('componentDidMount');
}
// 是否允许组件内部数据更新 setState 后调用或父组件重新 render 时
// 需要返回一个 boolean 值以决定是否更新
// 若该声明周期函数不写,则默认返回true,允许更新
// 若写该函数,则返回值省略时,返回undefined,即对应boolean值为false,将不再更新
shouldComponentUpdate(){
console.log('shouldComponentUpdate');
return true;
}
// 数据将要更新,组件将要重新渲染
UNSAFE_componentWillUpdate(){
console.log('componentWillUpdate');
// 若由组件内部数据更新引起,此时还组件内的数据没有更新
// 走完这个函数,将走 render 函数
// 执行 render 前,数据已经更新完毕
console.log('@',this.state);
}
// 组件内部数据更新或父组件重新render后,触发 shouldComponentUpdate ->
// componentWillUpdate -> render -> componentDidUpdate(当前这个),表示数据和组件已经更新完毕
// 会接收到两个参数,一个是旧的props,一个是旧的state
componentDidUpdate(preprops, prestate){
console.log('componentDidUpdate', preprops, prestate);
}
// 组件将要被卸载时调用
componentWillUnmount(){
console.log('componentWillUnmount');
}
// 组件内部数据更新时或父组件重新render时,该组件的render也重新调用
render(){
console.log('render',this.state);
return (
<div>
<h1>current number:{this.state.num}</h1>
<button onClick={this.autoIncrement}>click me to auto-increment</button><br/>
<button onClick={this.destroyComponent}>click me to distroy the component</button><br/>
<button onClick={this.forceRefresh}>click me to force refresh component</button>
</div>
)
}
}
ReactDOM.render(<OldTotalExample/>, document.getElementById('test'));
下方代码演示简单父子组件的使用、演示 UNSAFE_componentWillReceiveProps 生命周期函数相关的内容。
class Father extends React.Component{
state = {
currentYear:2023,
name:'tom',
age:25,
gender:'man'
}
render(){
let {currentYear, name, age, gender} = this.state;
return(
<div>
{
// 当 currentYear 更新时,子组件也会触发从 componentWillReceiveProps 到
// componentDidUpdate 的重新渲染链,这里的 currentYear 不是子组件所依赖的数据
}
<h1>{currentYear}</h1>
{
// 在父组件中使用子组件
}
<Children name={name} age={age} gender={gender}/>
<button onClick={()=>{this.setState({age:age + 1})}}>lick to add age</button>
<button onClick={()=>{this.setState({currentYear:currentYear + 1})}}>click into new year</button>
</div>
)
}
}
// 子组件也是继承于 React.Component
class Children extends React.Component{
/*
只要是父组件重新render了,子组件这个生命周期函数以及
shouldComponentUpdate、componentWillUpdate、render、componentDidUpdate
都会被接连调用(顺序即以上排列的顺序)
不管是不是子组件所依赖于父组件的 props 值被更新
*/
UNSAFE_componentWillReceiveProps(props){
// 已经接收到'新'的 props 了,
console.log(props);
}
render(){
return (
<div>
<h2>name: {this.props.name}</h2>
<h2>age: {this.props.age}</h2>
<h2>gender: {this.props.gender}</h2>
</div>
)
}
}
ReactDOM.render(<Father/>, document.getElementById('test'));
2、新 生命周期函数(9 - 3 + 2 = 8)
以下三个旧的生命周期函数不建议再去使用:
- UNSAFE_componentWillMount
- UNSAFE_componentWillUpdate
- UNSAFE_componentWillReceiveProps
新增了两个生命周期函数(实际使用的频率都比较低):
- statis getDerivedStateFromProps(props, state)
如果该组件是单纯由 props 决定数据渲染的或状态依赖于 props ,则可以使用到该静态方法。
该方法接收到两个参数,一个是props,一个是当前组件的state。
如果定义了静态 getDerivedStateFromProps, React将在调用render之前调用它,无论是在初始挂载时还是在后续更新时。
它应该返回一个对象来更新状态,或者返回null来表示不更新任何东西。
- getSnapshotBeforeUpdate(preProps, preState)
当组件即将要渲染到页面上时,将调用该方法。
该方法接收到两个参数,一个是旧的props,一个是当前组件旧的 state。
如使用该方法,则必须要返回一个快照值(snapshot)。可以是任何类型的数据,如数值、字符串、对象等,也可以是null,但不能是undefined。该快照值将作为执行 componentDidUpdate的第三个参数。