在具备许多组件的应用程序中,当组件被销毁时释放所占用的资源是很是重要的。html
组件从 被建立 到 被销毁 的过程称为组件的生命周期。react
组件的生命周期可分红三个状态:ajax
组件的生命周期可分为三个阶段:api
( 图片来源:projects.wojtekmaj.pl/react-lifec… )浏览器
( 图片来源:projects.wojtekmaj.pl/react-lifec… )安全
constructor(props);
复制代码
一般,在 React
中,构造函数仅用于如下两种状况:性能优化
this.state
赋值对象来初始化内部 state
。( 惟一能够直接修改 state
的地方)在 constructor()
函数中不要调用 setState()
方法。markdown
constructor(props) {
super(props);
// 不要在这里调用 this.setState()
this.state = { counter: 0 };
this.handleClick = this.handleClick.bind(this);
}
复制代码
static getDerivedStateFromProps(props, state)
复制代码
这个方法是 “如何用 props
初始化 state
” 的最佳实践。网络
⚠️ 注意,该方法在每次 render 前都会被调用。函数
此方法适用于罕见的用例(表单控件获取默认值)。当 state
是从 props
获取时,就必需要维护二者的一致性,这将会增长复杂度和 bug
。
shouldComponentUpdate(nextProps, nextState);
复制代码
当 props
或 state
发生变化时,shouldComponentUpdate()
会在渲染执行以前被调用。返回值默认为 true
。首次渲染或使用 forceUpdate()
时不会调用该方法。
此方法 仅做为性能优化 的方式而存在。它的工做通常能够由 PrueComponent 自动实现。
后续版本,
React
可能会将shouldComponentUpdate
仅视为提示,而且,当返回false
时,仍可能致使组件从新渲染。
render();
复制代码
用于描述 DOM
结构,组件中惟一必须实现的方法。
getSnapshotBeforeUpdate(prevProps, prevState);
复制代码
能在组件发生更改以前从 DOM
中捕获一些信息(例如,滚动位置)。今生命周期方法的任何返回值将做为参数传递给 componentDidUpdate()
。
componentDidMount();
复制代码
在组件挂载后(插入 DOM
树中)当即调用。在这里能够安全操做 DOM
节点、发送ajax
请求(DOM
节点的初始化)或一些反作用的事情(订阅)
若是你在这里调用了 setState
,它将触发额外渲染,虽然此渲染会发生在浏览器更新屏幕以前,但会致使性能问题。
componentDidUpdate(prevProps, prevState, snapshot);
复制代码
在更新后会被当即调用。首次渲染不会执行此方法。
⚠ 注意, 若是直接调用 setState()
,它必须被包裹在一个条件语句里,不然会致使死循环。
componentWillUnmount();
复制代码
在组件卸载及销毁以前直接调用,作一些资源释放操做,例如,清除 timer
,取消网络请求或清除在 componentDidMount()
中建立的订阅等。
⚠️ 注意:不该调用 setState()
,由于该组件将永远不会从新渲染。
用官方的经典 Clock
组件,能够清楚的展现出常见生命周期方法的应用:
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = { date: new Date() };
}
componentDidMount() {
this.timerID = setInterval(() => this.tick(), 1000);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
componentDidUpdate() {
console.log("component did update!");
}
tick() {
this.setState({
date: new Date(),
});
}
render() {
return (
<div> <h1>Hello, world!</h1> <h2>It is {this.state.date.toLocaleTimeString()}.</h2> </div>
);
}
}
ReactDOM.render(<Clock />, document.getElementById("root"));
复制代码
在组件第一次挂载时,设置一个定时器;同时,在组件卸载时,清除定时器。
state.date
发生改变时,会引起组件的从新渲染。
以特殊方式处理滚动位置的聊天线程:由于每一条新消息的置顶设定,没法让页面固定在某处,因此在每次更新前都须要计算调整滚动条的位置。
class ScrollList extends PureComponent {
state = {
messages: [],
};
getSnapshotBeforeUpdate() {
return this.rootNode.scrollHeight;
}
componentDidUpdate(prevProps, prevState, prevScrollHeight) {
const scrollTop = this.rootNode.scrollTop;
if (scrollTop < 5) return;
this.rootNode.scrollTop =
scrollTop + (this.rootNode.scrollHeight - prevScrollHeight);
}
render() {
return (
<div className="scroll-list" ref={(n) => (this.rootNode = n)}> {this.state.messages.map((msg) => ( <div>{msg}</div> ))} </div>
);
}
}
复制代码
在 DOM
更新前,经过 getSnapshotBeforeUpdate
获取原来的元素内容高度( scrollHeight
),并做为第三个参数传给 componentDidUpdate
;
在 componentDidUpdate
中,经过添加元素内容高度差值( this.rootNode.scrollHeight - prevScrollHeight
),调整滚动条位置( scrollTop
)。