前言
在vue中我们了解到,钩子函数就是vue生命周期中有一定执行顺序的接口函数,用户可以根据这些暴露的函数处理自己的数据,渲染页面.可以这样理解,钩子,钩子,挂载自己的东西
React组件也提供了生命周期的钩子函数去响应组件不同时刻的状态
React生命周期

由图我们可以简单了解到,React生命周期主要分为三个阶段:初始化,存在期,销毁期,每个生命周期阶段调用的钩子函数会略有不同,下面来详细了解下:
一、初始化/实例化
1.getDefaultProps
这个方法是用来设置组件默认的props,组件生命周期只会调用一次。但是只适合React.createClass直接创建的组件(使用ES6/ES7创建的这个方法不可使用),ES6/ES7可以使用下面方式:
//es7
class Component {
static defaultProps = {
name:KK,
age:18
}
}
//或者也可以在外面定义es6
//Compnent.defaultProps
2.getInitialState
设置state初始值,getDefaultProps只适合React.createClass使用。使用ES6初始化state方法如下:
class Component extends React.Component{
constructor(){
super();
this.state = {
num:-1
}
}
}
在这个方法中如果你想访问this.props
class Component extends React.Component{
constructor(props){
super(props)//=>类似与call继承
this.state = {
num:-1
}
console.log(this.props)
}
}
3.componentWillMount
- 在完成首次渲染之前调用,此时仍可以修改组件的state。
- 因为componentWillMount是在render之前执行,所以在这个方法中setState不会发生重新渲染(re-render);
- 通常情况下,推荐用constructor()方法代替;
4.render
JSX通过这里,解析成对应的虚拟DOM,格式大致如下:
class Component extends React.Component{
render(){
return (
<div></div>
)
}
}
5.componentDidMount
- 真实的DOM被渲染出来后调用,在该方法中可访问到真实的DOM元素。
- 这里可以加载服务器数据
- 这里可以使用setState()方法触发重新渲染(re-render);
二、存在期
1.componentWillReceiveProps
- 每当我们通过父组件更新子组件props时(这个也是唯一途径),这个方法就会被调用。
- 如果你只是调用this.setState()而不是从外部传入props, 那么不会触发componentWillReceiveProps(nextProps)函数;这就意味着: this.setState()方法不会触发componentWillReceiveProps(), props的改变或者props没有改变才会触发这个方法;
componentWillReceiveProps(nextProps){}
2.shouldComponentUpdate
- 在接收到新props或state时,或者说在componentWillReceiveProps(nextProps)后触发
- 字面意思,是否应该更新组件,默认返回true。当返回false时,后期函数就不会调用,组件不会再次渲染。
shouldComponentUpdate(nextProps,nextState){}
3.componentWillUpdate
在props或state发生改变或者shouldComponentUpdate(nextProps, nextState)触发后, 在render()之前
4.render
和实例化时的render一样
5.componentDidUpdate
这个方法在更新真实的DOM成功后调用,当我们需要访问真实的DOM时,这个方法就也经常用到
三、销毁期
componentWillUnmount
- 在组件卸载(unmounted)或销毁(destroyed)之前
- 这个方法可以让你处理一些必要的清理操作,比如无效的timers、interval,或者取消网络请求,或者清理任何在componentDidMount()中创建的DOM元素(elements);
测试代码:
import React from 'react';
import ReactDOM from 'react-dom';
class Temp extends React.Component {
constructor() {
super();
this.state = {msg: 'hello world!'};
console.log(`1=>执行构造函数`);
}
componentWillMount() {
console.log(`2=>第一次渲染之前`);
}
componentDidMount() {
console.log(`4=>第一次渲染之后`);
/*setTimeout(() => {
//=>2000MS后打算重新渲染组件(修改状态)
this.setState({
msg: 'hello world!'
});
}, 2000);*/
}
shouldComponentUpdate(nextProps, nextState) {
console.log(`5=>是否允许更新,返回TRUE是允许,反之不允许`, nextProps, nextState);
/*if (this.state.msg === nextState.msg) {
//=>重新设置的属性值和之前的是一样的,此时就不需要重新的进行渲染
return false;
}*/
return true;
}
componentWillUpdate(nextProps, nextState) {
console.log(`6=>更新之前`, nextState);
}
componentDidUpdate() {
console.log(`7=>更新之后`, this.state.msg);
}
//=>属性改变
componentWillReceiveProps(nextProps) {
//=>属性更改的时候,它优先于shouldComponentUpdate执行(它控制的是属性已经修改了,而SHOULD控制的是允许组件重新渲染)
//=>此时获取的PROPS的值还是原始值
console.log(`属性更改了`, nextProps);
}
render() {
console.log(`3=>渲染组件`, this.props);
return <h2>
{this.state.msg}
</h2>;
}
}
class Box extends React.Component {
constructor() {
super();
this.state = {n: 10};
}
componentDidMount() {
setTimeout(() => {
this.setState({
n: ++this.state.n
});
}, 2000);
}
render() {
return <div>
<h2>请说:</h2>
<Temp n={this.state.n}/>
{/*父组件把自己的状态信息当做属性值传递给子组件*/}
</div>;
}
}
ReactDOM.render(<div>
<Box/>
</div>, window.root);