在具備許多組件的應用程序中,當組件被銷燬時釋放所佔用的資源是很是重要的。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
)。