今天这一节,我们来说说React的生命周期。先上个全图。
React生命周期.png
我们先用原生JS来大概解释一波,简单来说就是一个组件的生老病死。(注:下面代码不包含全部生命周期阶段)
// 根节点
let root = document.querySelector("#root");
// create div
let div = document.createElement("div");
let state = 0;
// componenetWillMount
// render == update
div.innerHTML = `
<p class="number">${state}</p>
<button class="add">+1</button>
<button class="die">go die</button>
`;
// mount div
root.appendChild(div);
// mount 之后
document.querySelector('.add').onclick = () => {
state += 1;
// update div == render
document.querySelector('.number').innerHTML = state;
};
document.querySelector('.die').onclick = () => {
root.removeChild(div);
document.querySelector('.add').onclick = null;
document.querySelector('.die').onclick = null;
div = null; // destroy div
}
然后我们用React来举例。
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
class App extends React.Component {
static defaultProps = {
// 1. 加载默认属性
name: "Jason",
age: 23
};
constructor() {
super();
// 2. 加载默认状态
this.state = {
amount: 100,
};
}
componentWillMount() {
console.log('3. App组件将要挂载');
}
add() {
this.setState({
amount: this.state.amount + 1
});
}
render() {
console.log('4. App组件挂载渲染(之后的update也有render)')
return(
<div className="App">
<p>{this.props.name}, {this.props.age}</p>
<span>amount: {this.state.amount}</span>
<button onClick={() => this.add()}>+1</button>
</div>
);
}
componentDidMount() {
console.log('5. App组件挂载之后')
}
// 到此,App组件的「初始化阶段」结束,进入「进行时阶段」
componentWillUpdate() {
console.log('6. App组件将要更新啦!');
}
// 7. 这一步可以做性能优化点,判断是否真的要更新。
shouldComponentUpdate(nextPros, nextState) {
// 此处举例,再点击「add」按钮,如果amount值为偶数才显示更新后结果
// 注意:按照我们的逻辑,应该是取下一个state的值,即「nextState」
if (nextState.amount % 2 === 0) {
return true;
} else {
return false;
}
}
// 8. 重新render
componetDidUpdate() {
console.log('9. App组件更新完毕!')
}
// 10. 如果我们先操作UnMount
componentWillUnmount() {
// 在「Parent」组件中点击「go die」按钮,会销毁「App组件」
console.log('10. App组件即将销毁');
}
// 11. 当App组件从Parent组件收到的Props改变,执行。
componentWillReceiveProps() {
console.log('9. App组件接受的Props改变了')
}
// 12. 再次进入 第6步的「componentWillUpdate」
}
class Parent extends React.Component {
constructor() {
super();
this.state = {
hasChild: true,
n: 0
}
}
removeChild() {
// 消灭App组件
this.setState({
hasChild: false
});
}
render() {
return(
<div className="parent">
<button onClick = {() => this.removeChild()}>go die</button>
{
this.state.hasChild ? <App /> : null
}
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<Parent />, rootElement);
总结下:
(1)「初始化阶段」
- defaultProps:默认属性
- constructor:可以初始化state
- componentWillMount:组件即将挂载
- render:组件挂载渲染
- componentDidMount:组件挂载完毕
(2)「运行时阶段」
如果「state改变」(比如用this.setState改变)
- shouldComponentUpdate:是否需要更新组件?(性能优化点)
- componentWillUpdate:组件即将更新
- render:组件渲染
- componentDidUpdate: 组件完成更新
如果「props」改变(一般是指从「父组件」传到「当前组件」的props,「父组件」重新render)
- componentWillReceiveProps:当前组件接收到props时触发
- shouldComponentUpdate:是否需要更新组件?(性能优化点)
- componentWillUpdate:组件即将更新
- render:组件渲染
- componentDidUpdate: 组件完成更新
(3)「销毁阶段」
如果当前组件即将销毁前,触发「componentWillUnmount」事件。