首先介绍react16.3之前的生命周期;之后介绍react16.3的生命周期的变化
react16.3之前的生命周期
react的生命周期分为三个阶段:
- Mounting 挂载
- Updating 更新
- Unmounting 卸载
首先列举出所有的生命周期函数,再与这三个阶段对应、解释
constructor(props) {
console.log('constructor');
super(props);
}
componentWillMount() {
console.log('componentWillMount');
}
componentDidMount() {
console.log('componentDidMount');
}
componentWillReceiveProps(nextProps, nextState) {
console.log('componentWillReceiveProps');
}
shouldComponentUpdate(nextProps, nextState) {
console.log('shouldComponentUpdate');
return true;
}
componentWillUpdate(nextProps, nextState) {
console.log('componentWillUpdate');
}
componentDidUpdate(prevProps, prevState) {
console.log('componentDidUpdate');
}
componentWillUnmount(){
console.log('componentWillUnmount');
}
Mounting 挂载阶段:
- constructor():函数构造器
- 执行次数:1
- 作用:初始化
- componentWillMount:DOM挂载之前的钩子函数
* 执行次数:1
* 作用:DOM挂载前的操作 - componentDidMount:DOM挂载完成的钩子函数
* 执行次数:1
* 作用:DOM挂载完成后的操作:setState等
Updating 更新阶段:
- componentWillReceiveProps(nextProps, nextState):父组件传递的参数发生变化的钩子函数
* 执行次数:多次
* 触发条件:父组件重新render时触发,(不管向子组件传递的值是否发生变化都触发) - shouldComponentUpdate(nextProps, nextState):判断组件是否更新的钩子函数
* 执行次数:多次
* 触发条件:组件挂载之后,每次调用setState后都会调用shouldComponentUpdate判断是否需要重新渲染组件。默认返回true,需要重新render。 - componentWillUpdate(nextProps, nextState):组件将要更新的钩子函数
* 执行次数:多次
* 触发条件:shouldComponentUpdate返回true或者调用forceUpdate之后
,componentWillUpdate会被调用。 - componentDidUpdate(prevProps, prevState):组件完成更新的钩子函数
* 执行次数:多次
* 触发条件:除了首次render之后调用componentDidMount,其它render结束之后都是调用componentDidUpdate。
Unmounting 卸载阶段:
- componentWillUnmount():组件将要卸载的钩子函数
- 执行次数:1
- 触发条件:组件将要被卸载的时候调用。一般在componentDidMount里面注册的事件需要在这里删除;重置this.setState = (state,callback)=>{ return;};
附上代码,可自行运行查看运行顺序
/**
* react16.3前生命周期函数
*/
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
class Father extends Component {
constructor(props) {
super(props);
this.state = {
count: 1
}
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState((prevState, props) => ({
count: prevState.count + 1
}))
}
render() {
return (
)
}
}
class Child extends Component {
constructor(props) {
console.log('constructor');
super(props);
}
componentWillMount() {
console.log('componentWillMount');
}
componentDidMount() {
console.log('componentDidMount');
}
componentWillReceiveProps(nextProps, nextState) {
console.log('componentWillReceiveProps');
}
shouldComponentUpdate(nextProps, nextState) {
console.log('shouldComponentUpdate');
return true;
}
componentWillUpdate(nextProps, nextState) {
console.log('componentWillUpdate');
}
componentDidUpdate(prevProps, prevState) {
console.log('componentDidUpdate');
}
componentWillUnmount() {
console.log('componentWillUnmount');
}
render() {
console.log('render');
return (
子元素:
父组件属性count值: {this.props.count}
this.props.handleClick()}
style={{ display: "inline-block", padding: "3px 5px", color: "#ffffff", background: "green", borderRadius: "3px", cursor: "pointer" }}
>click me
)
}
}
ReactDOM.render(
, document.getElementById('root'))
运行结果如下
constructor
componentWillMount
render
componentDidMount
点击button按钮(click me)后的控制台运行结果如下:
constructor
componentWillMount
render
componentDidMount
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
render
componentDidUpdate
下图反映了React组件四条更新路径:
react16.3之后的生命周期
react16.3新增了一些生命周期函数:
getDerivedStateFromProps、getSnapshotBeforeUpdate
同时FB声明在react17将删除:
componentWillMount、componentWillReceiveProps、componentWillUpdate
在16.3的版本中将保留这三个函数,并添加了别名:
UNSAFE_componentWillMount、UNSAFE_componentWillReceiveProps、UNSAFE_componentWillUpdate
在此我们主要介绍
getDerivedStateFromProps、getSnapshotBeforeUpdate
- getDerivedStateFromProps(nextProps, prevState):从props派生出state
* 执行次数:多次
* 触发条件:组件实例化及接收新props后调用
* 替代:替代原来的componentWillReceiveProps,并且加载第一次时也调用 - getSnapshotBeforeUpdate(nextProps, prevState):从props派生出state
* 执行次数:多次
* 触发条件:组件render时调用
* 返回值:返回值传递给componentDidUpdate(prevProps, prevState, snapshot)
* 替代:替代原来的componentWillupdate
对上面的代码简单修改如下:
/**
* react16.3后生命周期
*/
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
class Father extends Component {
constructor(props) {
super(props);
this.state = {
count: 1
}
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState((prevState, props) => ({
count: prevState.count + 1
}))
}
render() {
return (
)
}
}
class Child extends Component {
constructor(props) {
console.log('constructor');
super(props);
this.state={
count:10
}
}
static getDerivedStateFromProps(nextProps, prevState) {
console.log('getDerivedStateFromProps');
return {
count: nextProps.count * 2,
};
}
componentDidMount() {
console.log('componentDidMount');
}
shouldComponentUpdate(nextProps, nextState) {
console.log('shouldComponentUpdate');
return true;
}
getSnapshotBeforeUpdate(prevProps, prevState) {
console.log('getSnapshotBeforeUpdate');
return 'aa';
}
componentDidUpdate(prevProps, prevState, snapshot) {
console.log('componentDidUpdate');
console.log(snapshot);
}
render() {
console.log('render');
return (
子元素:
父组件属性count值: {this.props.count}
this.props.handleClick()}
style={{ display: "inline-block", padding: "3px 5px", color: "#ffffff", background: "green", borderRadius: "3px", cursor: "pointer" }}
>click me
)
}
}
ReactDOM.render(
(
)
, document.getElementById('root'))
执行结果如下
constructor
getDerivedStateFromProps
render
componentDidMount
点击后如下:
constructor
getDerivedStateFromProps
render
componentDidMount
getDerivedStateFromProps
shouldComponentUpdate
render
getSnapshotBeforeUpdate
componentDidUpdate
aa
运行一下代码一看便知