1. 組件中在某個階段會自動執行的函數。
- 好比咱們執行使用render函數,在prop或者state變化時,render函數自動執行。
- 所以render函數就是一個生命週期函數。
2. constructor在組件建立的時候也會自動調用。可是他不是react獨有,是es6中的函數因此,咱們不將他列爲生命週期函數。javascript
1. initialization(組件初始化)
- 咱們在建立組件的時候須要繼承react Component這個基類,也就繼承這個react的基類,纔能有render(),生命週期等方法可使用,這也說明爲何函數組件不能使用這些方法的緣由。同時也讓組件能使用setState方法。
- 而後咱們在 constructor 構造函數中使用 super(props)來將父組件傳遞的props注入給這個組件,以及使用this.state初始化這個組件的屬性。
- 這一系列動做就是組件的初始化。
2. mount (組件的掛載)
- 此階段分爲三個時期
1. componentWillMount(掛載以前)
- 這個函數在組件掛載到DOM以前的時候執行,因此你在這裏引用setState方法,是不會引發組件的從新渲染。
- 一樣這裏作的事情若是放在constructor構造函數中去使用也是能夠的。
- 這個函數只會被調用一次,就是組件掛載到DOM以前的時候。其餘時候是不會觸發這個函數的。java
2. render(掛載中)
- 根據組件的props和state是否變化,變化即執行,這裏的變化要注意,並非值變化。只要從新賦值,新舊值相同也會執行。
- 而後return 一個React元素(描述組件,即UI),不負責組件實際渲染工做,以後由React自身根據此元素去渲染出頁面DOM。render是純函數(Pure function:函數的返回結果只依賴於它的參數;函數執行過程裏面沒有反作用。
- 不能在裏面執行this.setState,會有改變組件狀態的反作用。react
3. componentDidMount(掛載完成)
- 約定將ajax請求放在這個生命週期函數中
- 組件掛載到DOM後被執行,只會執行一次。
3. update (組件更新時)
- 首先咱們來了解一下什麼時組件更新。只有在經過setState函數使sate和props變化或從新賦值時才叫組件更新。
- setState引發父組件的render函數執行,同時也會引發它的子組件的render函數執行。
- 緣由是react虛擬DOM的diff算法,同級比較原理。
- 只要從新賦值就是組件更新,若是值並無變,也更新組件,這樣就會耗性能,也是咱們講同級比較的時候說的一個弊端。es6
- 接下來咱們瞭解一下有那些周期函數
1. componentWillReceiveProps(nextProps)
- 此方法只調用於props引發的組件更新過程當中,參數nextProps是父組件傳給當前組件的新props。但父組件render方法的調用不能保證重傳給當前組件的props是有變化的,因此在此方法中根據nextProps和this.props來查明重傳的props是否改變,以及若是改變了要執行啥,好比根據新的props調用this.setState出發當前組件的從新renderajax
2. shouldComponentUpdate(nextProps, nextState)
- 此方法經過比較nextProps,nextState及當前組件的this.props,this.state,返回true時當前組件將繼續執行更新過程,返回false則當前組件更新中止,以此可用來減小組件的沒必要要渲染,優化組件性能。ps:這邊也能夠看出,就算componentWillReceiveProps()中執行了this.setState,更新了state,但在render前(如shouldComponentUpdate,componentWillUpdate),this.state依然指向更新前的state,否則nextState及當前組件的this.state的對比就一直是true了。算法
3. componentWillUpdate(nextProps, nextState)
- 此方法在調用render方法前執行,在這邊可執行一些組件更新發生前的工做,通常較少用。數組
4. render
- render方法在上文講過,這邊只是從新調用。函數
5. componentDidUpdate(prevProps, prevState)
- 此方法在組件更新後被調用,能夠操做組件更新的DOM,prevProps和prevState這兩個參數指的是組件更新前的props和state
- 優化弊端
- 1.當由於父組件從新render,使得props從新被賦值,致使子組件跟着渲染.性能
/** * 方法一:解決上述弊端,能夠在shouldComponentUpdate函數,組件更新前進行判斷,props是否改變,再肯定是否執行從新渲染。 */ class Child extends Component { shouldComponentUpdate(nextProps){ if(nextProps.value === this.props.value){ return false } return true } render() { return <div>{this.props.value}</div> } } /** * 方法二: * 1.解決上述弊端,也能夠先將this.props.value賦值給子組件的state * 2.再在componentWillReceiveProps函數中,使用setState去從新給stae中的屬性賦值this.props.value * 3.文檔中提到,在該函數(componentWillReceiveProps)中調用 this.setState() 將不會引發第二次渲染。 * 4.由於componentWillReceiveProps是在props有變化的時候纔會觸發,因此在這裏面作this.setState()必定是有改變state */ // class Child extends Component { constructor(props) { super(props); this.state = { value: props.value // 先將this.props.value賦值給子組件的state }; } componentWillReceiveProps(nextProps) { // 在props有變化的時候纔會觸發這個方法 this.setState({value: nextProps.value}); // 從新賦值,引發render } render() { return <div>{this.state.value}</div> } }
- 2.組件自己調用setState方法,可是並無改變state中的值。優化
/** * 也是經過shouldComponentUpdate判斷新舊值是否改變,改變才作render */ class Test extends Component { constructor(props) { super(props); this.state = { value:1 } } shouldComponentUpdate(nextState){ // 應該使用這個方法判斷新舊值是否改變 if(nextState.value === this.state.value){ return false // 沒有改變返回false } return true } changeState = () => { // 雖然調用了setState ,但state並沒有變化 const value = this.state.value this.setState({ value }) } render() { return <div onClick = {this.changeState}>{this.state.value}</div> } }
4. 卸載階段(componentWillUnmount)
- 只有一個生命週期方法componentWillUnmount
- 此方法在組件被卸載前調用,能夠在這裏執行一些清理工做,好比清楚組件中使用的定時器,清楚componentDidMount中手動建立的DOM元素等,以免引發內存泄漏。
5. 在react組件中,除了render函數,其餘任何生命週期函數均可以不寫,由於組件繼承了react中的 Component,Component內置了其餘的生命週期函數