React-Native開發三 React Native元件生命週期
1 前言
大家都知道React Native其實是由很多元件構成,開發RN介面的過程就是合理的組織各個元件的過程,在這其中需要不斷的拆分和優化元件。因此理解RN元件的生命週期很重要,這樣我們才能合理的在元件中進行我們的事務。
2 React Native元件生命週期
RN元件的生命週期分為四個階段 分別是:建立階段 例項化階段 執行(更新)階段 銷燬階段
整體流程圖如下(借用別人的圖)
下面分別介紹各個元件的生命週期
3 建立階段
建立階段主要發生在建立元件類的時候,在這個階段中主要是初始化元件的屬性型別和預設屬性,例如元件的props的初始化,和一些變數的初始化
一般在這個階段中主要做的工作如下:
初始化props,在ES6中定義靜態的方法來初始化props
//定義預設屬性
static defaultProps = {
autoPlay:false,
maxLoops:10,
};
//定義proTypes
static propTypes = {
autoPlay:PropTypes.bool.isRequired,
maxLoops:PropTypes.number.isRequired,
};
注意:初始化一般只執行一次,這一點與java中類的初始化類似
4 例項化階段
例項化階段主要從建構函式開始,主要進行元件的例項化過程,包括載入,渲染等
1 constructor(props)
這裡是對控制元件的一些狀態進行初始化,由於該函式不同於defaultProps,在以後的過程中,會再次呼叫,所以可以將控制控制元件的狀態的一些變數放在這裡初始化。
主要用於state的定義和初始化。
在ES6裡,通過constructor(構造器)對狀態進行初始化
//元件例項化時呼叫 可呼叫多次
constructor(props){
super(props);
console.log("constructor");
this.state = {
loopsRemaining:this.props.maxLoops,
} ;
}
2 componentWillMount()
該函式表示元件將要被載入的回撥,該函式的呼叫在元件初始化了狀態即呼叫建構函式之後,並且在render()之前。
主要用於進行一些業務的初始化。
函式只調用依次,如果呼叫setState(),其結果可以被render()看到
//例項化 準備載入元件
componentWillMount() {
console.log('componentWillMount');
}
3 render()
render是一個元件必須有的方法,形式為一個函式,渲染介面,並返回JSX或其他元件來構成DOM,和Android的XML佈局、WPF的XAML佈局類似,只能返回一個頂級元素。
render() {
console.log("render()");
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
<Text style={styles.instructions}>
To get started, edit App.js
</Text>
<Text style={styles.instructions}>
{instructions}
</Text>
<Greeting name='React 1'/>
<Greeting name='React 2'/>
<Greeting name='React 3'/>
<TouchableHighlight onPress={this._onPressButton}>
<Text>Button</Text>
</TouchableHighlight>
</View>
);
}
render主要用於渲染介面,因此這個函式和UI相關,一般會用JSX語言來插入各種元件,以實現整個頁面的構建
4 componentDidMount()
該函式在render()之後,表示元件已經被載入完成。這個函式呼叫時表示其虛擬 DOM 已經構建完成,你可以在這個函式開始獲取其中的元素或者子元件了。需要注意的是,RN 框架是先呼叫子元件的 componentDidMount(),然後呼叫父元件的函式。從這個函式開始,就可以和 JS 其他框架互動了,例如設定計時 setTimeout 或者 setInterval,或者發起網路請求。這個函式也是隻被呼叫一次。這個函式之後,就進入了穩定執行狀態,等待事件觸發。
componentDidMount() {
console.log('componentDidMount');
}
到這裡整個例項化階段就算完成了,我們來看各個函式的呼叫過程,執行效果如下:
注意各個函式呼叫順序。
接下來就是執行階段了,執行階段會等待事件的出發,一旦出發事件,將會有執行階段的流程。
5 執行階段
執行階段在例項化階段之後,執行階段主要發生在使用者操作之後,或者父元件有更新時,此時子元件需要進行相應的事件出發。
觸發流程如下:
1 componentWillReceiveProps(nextProps)
當元件接收到新的props時,會觸發該函式。在該函式中,通常可以呼叫setState()來完成對state的修改。
注意:屬性一般是父元件傳遞給子元件的,
//在元件渲染完成之後,當reactNative元件接受到新的props時,這個函式將被呼叫,這個函式接受一個object引數,object裡時新的props。
componentWillReceiveProps(nextProps) {
this.setState({loopsRemaining:nextProps.maxLoops});
console.log('componentWillReceiveProps' + nextProps.value);
}
輸入引數 nextProps 是即將被設定的屬性,舊的屬性還是可以通過 this.props 來獲取。在這個回撥函式裡面,你可以根據屬性的變化,通過呼叫 this.setState() 來更新你的元件狀態,這裡呼叫更新狀態是安全的,並不會觸發額外的 render() 呼叫。如下
2 shouldComponentUpdate(nextProps, nextState)
表示元件是否需要更新,該函式返回布林值(決定是否需要更新元件),當不需要更新時可以複寫該函式返回false
//返回布林值(決定是否需要更新元件)
shouldComponentUpdate(nextProps,nextState){
console.log("shouldComponentUpdate");
return true;
}
輸入引數 nextProps 和上面的 componentWillReceiveProps 函式一樣,nextState 表示元件即將更新的狀態值。這個函式的返回值決定是否需要更新元件,如果 true 表示需要更新,繼續走後面的更新流程。否者,則不更新,直接進入等待狀態。
預設情況下,這個函式永遠返回 true 用來保證資料變化的時候 UI 能夠同步更新。在大型專案中,你可以自己過載這個函式,通過檢查變化前後屬性和狀態,來決定 UI 是否需要更新,能有效提高應用效能。
3 componentWillUpdate(nextProps, nextState)
當元件需要更新時,就會回撥該函式,然後就會呼叫render()更新元件
//元件將要更新
componentWillUpdate(nextProps, nextState){
console.log("componentWillUpdate");
}
輸入引數與 shouldComponentUpdate 一樣,在這個回撥中,可以做一些在更新介面之前要做的事情。需要特別注意的是,在這個函式裡面,你就不能使用 this.setState 來修改狀態。這個函式呼叫之後,就會把 nextProps 和 nextState 分別設定到 this.props 和 this.state 中。緊接著這個函式,就會呼叫 render() 來更新介面了。
4 render()
再確定需要更新元件時,呼叫render,根據diff演算法,渲染介面,生成需要更新的虛擬DOM資料。
5 componentDidUpdate()
虛擬DOM同步到DOM中後,執行該方法,可以在這個方法中做DOM操作。
//元件已經更新
componentDidUpdate() {
console.log("componentDidUpdate");
}
除了首次render之後呼叫componentDidMount,其它render結束之後都是呼叫componentDidUpdate。
componentWillMount、componentDidMount和componentWillUpdate、componentDidUpdate可以對應起來。區別在於,前者只有在掛載的時候會被呼叫;而後者在以後的每次更新渲染之後都會被呼叫。
注意:絕對不要在componentWillUpdate和componentDidUpdate中呼叫this.setState方法,否則將導致死迴圈
整個執行階段結果如下:
6 銷燬階段
當元件不需要存在時,就會進行元件的銷燬階段,該階段只有一個方法componentWillUnmount()
1 componentWillUnmount()
該方法中做一些元件清除的工作,比如銷燬定時器等,取消網路請求等
//銷燬階段 元件將要銷燬
componentWillUnmount(){
console.log("componentWillUnmount");
}
7 RN 元件生命週期總結
根據前面的RN生命週期介紹,下面總結一下各個生命週期的呼叫次數和能否使用setState()來改變狀態
總結:RN元件的生命週期還是比較清晰的,與Activity最大的區別就是將例項化階段和後續的更新階段分開了。