【ReactJS】通過一個例子學習React元件的生命週期
原始碼
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>React-props</title>
<script src ="https://cdn.bootcss.com/react/15.4.2/react.min.js"></script>
<script src="https://cdn.bootcss.com/react/15.4.2/react-dom.min.js"></script>
<script src="https://cdn.bootcss.com/babel-standalone/6.22.1/babel.min.js"></script>
</head>
<body>
<div id="demo" ></div>
<script type="text/babel">
var AddCount=React.createClass({
getInitialState:function(){
console.log('1...getInitialSate');
return {count:1};
},
componentWillMount:function(){
console.log('2...componentWillMount' );
},
componentDidMount:function(){
console.log('3...componentDidMount');
},
componentWillUpdate:function(){
console.log('4...componentWillUpdate');
},
componentDidUpdate:function(){
console.log('4...componentDidUpdate');
},
handleClick:function(event){
this.setState({count:this.state.count+1})
},
render:function(){
return(
<p>
{this.state.count}<br/>
<button onClick={this.handleClick}>Add</button>
</p>
)
}
})
ReactDOM.render(
<AddCount/>,
document.getElementById("demo")
);
</script>
</body>
</html>
效果圖
元件的生命週期
為了理解 React 的工作過程,我們就必須要了解 React 元件的生命週期,如同人有生老病死,自然界有日月更替,每個元件在網頁中也會被建立、更新和刪除,如同有生命的機體一樣。
React 嚴格定義了元件的生命週期,生命週期可能會經歷如下三個過程:
- 裝載過程(Mount),也就是把元件第一次在DOM樹中渲染的過程;
- 更新過程(Update),當元件被重新渲染的過程;
- 解除安裝過程(Unmount),元件從DOM中刪除的過程;
三種不同的過程,React 庫會依次呼叫元件的一些成員函式,這些函式稱為生命週期函式。所以,要定製一個React元件,實際上就是定製這些生命週期函式。
裝載過程
當元件第一次被渲染的時候,依次呼叫的函式是如下這些:
- constructor
- getInitialState
- getDefaultProps
- componentWillMount
- render
- componentDidMount
constructor、getInitialState、getDefaultProps和render我在 深入理解prop、state與render函式 有記載過,若不懂可以跳轉檢視。
這裡主要說下 componentWillMount 和 componentDidMount。
在裝載過程中,componentWillMount 會在呼叫 render 函式之前被呼叫,componentDidMount 會在呼叫 render 函式之後被呼叫,這兩個函式就像是 render 函式的前哨和後衛,一前一後,把 render 函式夾住,正好分別做 render 前後必要的工作。
不過,我們通常不用定義 componentWillMount 函式,顧名思義,componentWillMount 發生在“將要裝載”的時候,這個時候沒有任何渲染出來的結果,即使呼叫 this.setState 修改狀態也不會引發重新繪製,一切都遲了。換句話說,可以在這個 componentWillMount 中做的事情,都可以提前到 constructor 中間去做,可以認為這個函式存在的主要目的就是為了和 componentDidMount 對稱。
而 componentWillMount 的這個兄弟 componentDidMount 作用就大了。
需要注意的是,render 函式被呼叫完之後,componentDidMount 函式並不是會被立刻呼叫,componentDidMount 被呼叫的時候,render 函式返回的東西已經引發了渲染,元件已經被“裝載”到了DOM樹上。
之所以會有上面的現象,是因為 render 函式本身並不往DOM樹上渲染或者裝載內容,它只是返回一個JSX表示的物件,然後由 React 庫來根據返回物件決定如何渲染。所以,只有React庫呼叫n個元件的render函式之後,才有可能完成裝載,這時候才會依次呼叫各個元件的 componentDidMount 函式作為裝載過程的收尾。
更新過程
更新過程會依次呼叫下面的生命週期函式,其中render函式和裝載過程一樣,沒有差別。
- componentWillReceiveProps
- shouldComponentUpdate
- componentWillUpdate
- render
- componentDidUpdate
除了render函式,shouldComponentUpdate可能是React元件生命週期中最重要的一個函數了。
說 render 函式重要,是因為 render 函式決定了該渲染什麼,而說 shouldComponentUpdate 函式重要,是因為它決定了一個元件什麼時候不需要渲染。
render 和 shouldComponentUpdate 函式,也是React生命週期函式中唯二兩個要求有返回結果的函式。render 函式的返回結果將用於構造DOM物件,而 shouldComponentUpdate 函式返回一個布林值,告訴 React 庫這個元件在這次更新過程中是否要繼續。
在更新過程中,React 庫首先呼叫 shouldComponentUpdate 函式,如果這個函式返回 true,那就會繼續更新過程,接下來呼叫 render 函式;反之,如果得到一個 false,那就立刻停止更新過程,也就不會引發後續的渲染了。
說 shouldComponentUpdate 重要,就是因為只要使用恰當,他就能夠大大提高 React 元件的效能,雖然 React 的渲染效能已經很不錯了,但是,不管渲染有多快,如果發現沒必要的重新渲染,那就乾脆不用渲染好了,速度會更快。
我們知道 render 函式應該是一個純函式,這個純函式的邏輯輸入就是元件的 props 和 state。所以,shouldComponentUpdate 的引數就是接下來的 props 和 state 值。如果我們要定義 shouldComponentUpdate,那就根據這兩個引數,外加 this.props 和 this.state 來判斷出是返回 true 還是返回 false。
解除安裝過程
React元件的解除安裝過程只涉及一個函式 componentWillUnmount,當 React 元件要從DOM樹上刪除掉之前,對應的 componentWillUnmount 函式會被呼叫,所以這個函式適合做一些清理性的工作。
和裝載過程與更新過程不一樣,這個函式沒有配對的 Did 函式,就一個函式,因為解除安裝完就完了,沒有“解除安裝完再做的事情”。
每當元件使用完成,這個元件就必須從DOM中銷燬,此時該方法就會被自動呼叫。當我們在元件中使用了setInterval,那我們就需要在這個方法中呼叫clearTimeout。