最近在学习React,发现其中的生命周期跟Vue有一些共同点,但也有比较明显的区别,并且执行顺序也值得讨论一下,于是总结了一些资料在这里,作为学习记录。
由ReactDOM.render()触发 —— 初次渲染
由组件内部this.setSate()或父组件重新render触发或强制更新forceUpdate()
由ReactDOM.unmountComponentAtNode()触发
import React, { Component } from 'react';
import { Button } from 'antd';
import Child from './child';
const parentStyle = {
padding: 40,
margin: 20,
backgroundColor: 'LightCyan',
};
const NAME = 'Parent 组件:';
export default class Parent extends Component {
constructor() {
super();
console.log(NAME, 'constructor');
this.state = {
count: 0,
mountChild: true,
};
}
static getDerivedStateFromProps(nextProps, prevState) {
console.log(NAME, 'getDerivedStateFromProps');
return null;
}
componentDidMount() {
console.log(NAME, 'componentDidMount');
}
shouldComponentUpdate(nextProps, nextState) {
console.log(NAME, 'shouldComponentUpdate');
return true;
}
getSnapshotBeforeUpdate(prevProps, prevState) {
console.log(NAME, 'getSnapshotBeforeUpdate');
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
console.log(NAME, 'componentDidUpdate');
}
componentWillUnmount() {
console.log(NAME, 'componentWillUnmount');
}
/**
* 修改传给子组件属性 count 的方法
*/
changeNum = () => {
let { count } = this.state;
this.setState({
count: ++count,
});
};
/**
* 切换子组件挂载和卸载的方法
*/
toggleMountChild = () => {
const { mountChild } = this.state;
this.setState({
mountChild: !mountChild,
});
};
render() {
console.log(NAME, 'render');
const { count, mountChild } = this.state;
return (
<div style={parentStyle}>
<div>
<h3>父组件</h3>
<Button onClick={this.changeNum}>改变传给子组件的属性 count</Button>
<br />
<br />
<Button onClick={this.toggleMountChild}>卸载 / 挂载子组件</Button>
</div>
{mountChild ? <Child count={count} /> : null}
</div>
);
}
}
import React, { Component } from 'react';
import { Button } from 'antd';
const childStyle = {
padding: 20,
margin: 20,
backgroundColor: 'LightSkyBlue',
};
const NAME = 'Child 组件:';
export default class Child extends Component {
constructor() {
super();
console.log(NAME, 'constructor');
this.state = {
counter: 0,
};
}
static getDerivedStateFromProps(nextProps, prevState) {
console.log(NAME, 'getDerivedStateFromProps');
return null;
}
componentDidMount() {
console.log(NAME, 'componentDidMount');
}
shouldComponentUpdate(nextProps, nextState) {
console.log(NAME, 'shouldComponentUpdate');
return true;
}
getSnapshotBeforeUpdate(prevProps, prevState) {
console.log(NAME, 'getSnapshotBeforeUpdate');
return null;
}
componentDidUpdate(prevProps, prevState, snapshot) {
console.log(NAME, 'componentDidUpdate');
}
componentWillUnmount() {
console.log(NAME, 'componentWillUnmount');
}
changeCounter = () => {
let { counter } = this.state;
this.setState({
counter: ++counter,
});
};
render() {
console.log(NAME, 'render');
const { count } = this.props;
const { counter } = this.state;
return (
<div style={childStyle}>
<h3>子组件</h3>
<p>父组件传过来的属性 count : {count}</p>
<p>子组件自身状态 counter : {counter}</p>
<Button onClick={this.changeCounter}>改变自身状态 counter</Button>
</div>
);
}
}
从五种组件状态改变的时机来探究生命周期的执行顺序
父子组件第一次进行渲染加载时:
控制台的打印顺序为:
点击子组件 [改变自身状态counter] 按钮,其 [自身状态counter] 值会 +1, 此时控制台的打印顺序为:
点击父组件中的 [改变传给子组件的属性 count] 按钮,则界面上 [父组件传过来的属性 count] 的值会 + 1,控制台的打印顺序为:
点击父组件中的 [卸载 / 挂载子组件] 按钮,则界面上子组件会消失,控制台的打印顺序为:
再次点击父组件中的 [卸载 / 挂载子组件] 按钮,则界面上子组件会重新渲染出来,控制台的打印顺序为: