import React, { Component } from 'react'; import { AppRegistry, Text } from 'react-native'; class myFirstApp extends Component { render() { return ( <Text>Hello world!</Text> ); } } AppRegistry.registerComponent('myFirstApp', () => myFirstApp);
class Greeting extends Component { render() { return ( <View> <Text>Hello {this.props.name}</Text> </View> ); } } export default class myFirstApp extends Component { render() { return ( <View style={{ alignItems: 'center' }}> <Greeting name='react!' /> <Greeting name='react-native' /> <Greeting name='android' /> </View> ) } }
在constructor中初始化state,而後在須要修改時調用setState方法。node
constructor(props){ super(props); this.state = { count: 0, } } doUpdateCount(){ this.setState({ count: this.state.count+1 }) } <Text>當前計數是:{this.state.count}</Text> <TouchableOpacity onPress={this.doUpdateCount.bind(this)} style={{padding: 5,backgroundColor: '#ccc'}}> <Text>點我開始計數</Text> </TouchableOpacity>
<View> <Text style={[styles.bigblue],{backgroundColor: '#0f0'}}>style set</Text> <Text style={[styles.bigblue, {backgroundColor: '#00f'}]}>style set</Text> <Text style={{color:'#f00'}}>just red</Text> <Text style={styles.red}>just red</Text> <Text style={styles.bigblue}>just bigblue</Text> <Text style={[styles.bigblue, styles.red]}>bigblue, then red</Text> <Text style={[styles.red, styles.bigblue]}>red, then bigblue</Text> </View> const styles = StyleSheet.create({ bigblue: { color: 'blue', fontWeight: 'bold', fontSize: 30, }, red: { color: 'red', }, });
(1)指定寬高
React Native中的尺寸都是無單位的,表示的是與設備像素密度無關的邏輯像素點。react
<View> <View style={{width: 50, height: 50, backgroundColor: 'powderblue'}} /> <View style={{width: 100, height: 100, backgroundColor: 'skyblue'}} /> <View style={{width: 150, height: 150, backgroundColor: 'steelblue'}} /> </View>
(2)彈性(Flex)寬高android
使用flex:1來指定某個組件擴張以撐滿全部剩餘的空間。若是有多個並列的子組件使用了flex:1,則這些子組件會平分父容器中剩餘的空間。若是這些並列的子組件的flex值不同,則誰的值更大,誰佔據剩餘空間的比例就更大。
組件可以撐滿剩餘空間的前提是其父容器的尺寸不爲零。若是父容器既沒有固定的width和height,也沒有設定flex,則父容器的尺寸爲零。其子組件若是使用了flex,也是沒法顯示的。git
<View style={{flex: 1}}> <View style={{flex: 1, backgroundColor: 'powderblue'}} /> <View style={{flex: 2, backgroundColor: 'skyblue'}} /> <View style={{flex: 3, backgroundColor: 'steelblue'}} /> </View>
(3)react native沒有寬高100%的設置,因此若是須要讓元素撐滿屏幕,須要:github
import { Dimensions, View } from 'react-native'; <View style={{width: Dimensions.get('window').width,height: Dimensions.get('window').height}} />
flexDirection
的默認值是column而不是row,flex也只能指定一個數字值。
flexDirection能夠決定佈局的主軸。子元素是應該沿着水平軸(row
)方向排列,仍是沿着豎直軸(column
)方向排列呢?默認值是豎直軸(column)方向。justifyContent
能夠決定其子元素沿着主軸的排列方式。子元素是應該靠近主軸的起始端仍是末尾段分佈呢?亦或應該均勻分佈?對應的這些可選項有:flex-start,center,flex-end,space-around以及space-between
。alignItems
能夠決定其子元素沿着次軸(與主軸垂直的軸,好比若主軸方向爲row,則次軸方向爲column)的排列方式。子元素是應該靠近次軸的起始端仍是末尾段分佈呢?亦或應該均勻分佈?對應的這些可選項有:flex-start,center,flex-end以及stretch
。json
<View style={{ flex: 1, flexDirection: 'column', justifyContent: 'center', alignItems: 'center', }}> <View style={{width: 50, height: 50, backgroundColor: 'powderblue'}} /> <View style={{width: 50, height: 50, backgroundColor: 'skyblue'}} /> <View style={{width: 50, height: 50, backgroundColor: 'steelblue'}} /> </View>
TextInput
是一個容許用戶輸入文本的基礎組件。它有一個名爲onChangeText
的屬性,此屬性接受一個函數,而此函數會在文本變化時被調用。另外還有一個名爲onSubmitEditing
的屬性,會在文本被提交後(用戶按下軟鍵盤上的提交鍵)調用(注意react
中的onChange
對應的是rn中的onChangeText
)。react-native
constructor(props) { super(props); this.state = {text: ''}; } render() { return ( <View style={{padding: 10}}> <TextInput style={{height: 40}} placeholder="Type here to translate!" onChangeText={(textCont) => this.setState({text:textCont})} /> <Text style={{padding: 10, fontSize: 42}}> {this.state.text.split(' ').map((word) => word && 'xhh').join()} </Text> </View> ); }
import React, { Component } from 'react'; import { ScrollView, View } from 'react-native'; export default class MyScrollView extends Component { getScrollViewList(){ let scrollViewList = []; let colorList = ['red','green','blue','purple']; for(let i=0;i<colorList.length;i++) { var ViewItem = <View key={i} style={{ width: 420, height: 150, backgroundColor: colorList[i] }}></View>; scrollViewList.push(ViewItem); } console.log(scrollViewList); return scrollViewList; } render(){ return ( <ScrollView horizontal={true}> { this.getScrollViewList() } </ScrollView> ) } }
若是頁面內容一屏展現不完,須要滾動觀看那就可使用ScrollView
了。數組
ListView組件用於顯示一個垂直的滾動列表,其中的元素之間結構近似而僅數據不一樣。
ListView更適於長列表數據,且元素個數能夠增刪。和ScrollView不一樣的是,ListView並不當即渲染全部元素,而是優先渲染屏幕上可見的元素。
ListView組件必須的兩個屬性是dataSource和renderRow。dataSource是列表的數據源,而renderRow則逐個解析數據源中的數據,而後返回一個設定好格式的組件來渲染。
rowHasChanged函數也是ListView的必需屬性。這裏咱們只是簡單的比較兩行數據是不是同一個數據(===符號只比較基本類型數據的值,和引用類型的地址)來判斷某行數據是否變化了。網絡
import React, { Component } from 'react'; import { ListView, Text, View } from 'react-native'; export class ListViewBasics extends Component { // 初始化模擬數據 constructor(props) { super(props); const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}); this.state = { dataSource: ds.cloneWithRows([ 'John', 'John', 'James', 'Jimmy', 'Jackson', 'Jillian', 'Julie', 'Devin' ]) }; } render() { return ( <View style={{flex: 1,width: 150,height: 100,marginTop: 5, marginBottom: 5 }}> <ListView dataSource={this.state.dataSource} renderRow={(myRowData) => <Text>{myRowData}</Text>} /> </View> ); } }
import React, { Component } from 'react'; import { TouchableOpacity, Text, View } from 'react-native'; export default class FetchAjax extends Component { constructor(){ super(); this.state = { textDesc: 'initialText', } } // 初始化模擬數據 getData(){ fetch('http://facebook.github.io/react-native/movies.json') .then((response) => response.json()) .then((responseJson) => { console.log(responseJson); this.setState({ textDesc: responseJson.movies[0].title, }) }) .catch((error) => { console.error(error); }); } render() { return ( <View> <TouchableOpacity style={{ padding: 5,borderWidth:1, borderColor:'#aaa',borderRadius:4 }} onPress={this.getData.bind(this)} > <Text>Click Get Data</Text> </TouchableOpacity> <Text>{this.state.textDesc}</Text> </View> ); } }
導航方法:
若是你獲得了一個navigator對象的引用(譯註:再次推薦仔細閱讀此教程,理解如何在renderScene方法中傳遞navigator對象,不然直接調用會報undefined錯誤),則能夠調用許多方法來進行導航:getCurrentRoutes()
- 獲取當前棧裏的路由,也就是push進來,沒有pop掉的那些。jumpBack()
- 跳回以前的路由,固然前提是保留如今的,還能夠再跳回來,會給你保留原樣。jumpForward()
- 上一個方法不是調到以前的路由了麼,用這個跳回來就行了。jumpTo(route)
- 跳轉到已有的場景而且不卸載。push(route)
- 跳轉到新的場景,而且將場景入棧,你能夠稍後跳轉過去pop()
- 跳轉回去而且卸載掉當前場景replace(route)
- 用一個新的路由替換掉當前場景replaceAtIndex(route, index)
- 替換掉指定序列的路由場景replacePrevious(route)
- 替換掉以前的場景resetTo(route)
- 跳轉到新的場景,而且重置整個路由棧immediatelyResetRouteStack(routeStack)
- 用新的路由數組來重置路由棧popToRoute(route)
- pop到路由指定的場景,在整個路由棧中,處於指定場景以後的場景將會被卸載。popToTop()
- pop到棧中的第一個場景,卸載掉全部的其餘場景。
屬性:configureScene [function]
可選的函數,用來配置場景動畫和手勢。會帶有兩個參數調用,一個是當前的路由,一個是當前的路由棧。而後它應當返回一個場景配置對象。具體有哪些能夠看這個目錄:node_modules/react-native/Libraries/CustomComponents/Navigator/NavigatorSceneConfigs.js
app
(route, routeStack) => Navigator.SceneConfigs.FloatFromRight Navigator.SceneConfigs.PushFromRight (默認) Navigator.SceneConfigs.FloatFromRight Navigator.SceneConfigs.FloatFromLeft Navigator.SceneConfigs.FloatFromBottom Navigator.SceneConfigs.FloatFromBottomAndroid Navigator.SceneConfigs.FadeAndroid Navigator.SceneConfigs.HorizontalSwipeJump Navigator.SceneConfigs.HorizontalSwipeJumpFromRight Navigator.SceneConfigs.VerticalUpSwipeJump Navigator.SceneConfigs.VerticalDownSwipeJump
initialRoute [object]
定義啓動時加載的路由。路由是導航欄用來識別渲染場景的一個對象。initialRoute必須是initialRouteStack中的一個路由。initialRoute默認爲initialRouteStack中最後一項。initialRouteStack [object]
提供一個路由集合用來初始化。若是沒有設置初始路由的話則必須設置該屬性。若是沒有提供該屬性,它將被默認設置成一個只含有initialRoute的數組。navigationBar [node]
可選參數,提供一個在場景切換的時候保持的導航欄。navigator [object]
可選參數,提供從父導航器得到的導航器對象。onDidFocus [function]
每當導航切換完成或初始化以後,調用此回調,參數爲新場景的路由。onWillFocus [function]
會在導航切換以前調用,參數爲目標路由。renderScene [function]
必要參數。用來渲染指定路由的場景。調用的參數是路由和導航器。
(route, navigator) => <MySceneComponent title={route.title} navigator={navigator} />
sceneStyle [View#style]
將會應用在每一個場景的容器上的樣式。
index.android.js:
configureScene(route){ if(route.name == 'FirstPage'){ return Navigator.SceneConfigs.FloatFromBottom } return Navigator.SceneConfigs.FloatFromRight; } renderScene(router, navigator){ let Component = router.component; switch(router.name){ case "FirstPage": Component = FirstPage; break; case "SecondPage": Component = MySecondPage; break; } return <Component {...router.params} navigator={navigator} /> } renderHead(){ return( <View style={{height:60,position:'absolute',top:0,left:0,right:0,backgroundColor:'#666',justifyContent: 'center',alignItems: 'center',borderWidth:1,borderColor:'#ccc'}}> <Text> {'Navigator Bar'} </Text> </View> ) } <Navigator navigationBar = {this.renderHead()} initialRoute={{name: 'FirstPage'}} configureScene={this.configureScene} renderScene={this.renderScene.bind(this)} />
navigator.js:
import React, { Component } from 'react'; import { Text, View, TouchableOpacity } from 'react-native'; import MySecondPage from './navigatorPage'; export default class FirstPage extends Component { onPressButton() { this.props.navigator.push({ component: MySecondPage, params : { param1 : 'param1Value' }, type: 'Bottom' }) console.log(this.props.navigator.getCurrentRoutes()); } componentWillUnmount(){ console.log('FirstPage-componentWillUnmount'); } render(){ return( <View style={{marginTop: 60, flex:1,justifyContent: 'center',alignItems: 'center',}}> <Text>{'first Page'}</Text> <TouchableOpacity onPress={()=>this.onPressButton()}> <Text>點擊跳轉到第二頁</Text> </TouchableOpacity> </View> ) } }
navigatorPage.js:
import React, { Component } from 'react'; import { Text, View, TouchableOpacity } from 'react-native'; import MyThirdPage from './navigatorOtherPage'; export default class MySecondPage extends Component { onPressButton() { this.props.navigator.push({ component: MyThirdPage, type: 'Right' }) console.log(this.props.param1); //param1Value console.log(this.props.navigator.getCurrentRoutes()); } componentWillUnmount(){ console.log('MySecondPage-componentWillUnmount'); } render(){ return( <View style={{marginTop: 60, flex:1,justifyContent: 'center',alignItems: 'center',}}> <Text>{'second Page'}</Text> <TouchableOpacity onPress={()=>this.onPressButton()}> <Text>點擊跳轉到第三頁</Text> </TouchableOpacity> </View> ) } }
navigatorOtherPage.js:
import React, { Component } from 'react'; import { Text, View, TouchableOpacity } from 'react-native'; import FirstPage from './navigator'; import MySecondPage from './navigatorPage'; export default class MyThirdPage extends Component { // <TouchableOpacity onPress={()=>this.props.navigator.pop()}> // <Text>返回到第二頁</Text> // </TouchableOpacity> // <TouchableOpacity onPress={()=>this.props.navigator.replace({component: FirstPage})}> // <Text>返回到第一頁</Text> // </TouchableOpacity> // 就只執行了一次 // <TouchableOpacity onPress={()=>this.props.navigator.replaceAtIndex({component: FirstPage}, 2)}> // <Text>返回到第一頁</Text> // </TouchableOpacity> // <TouchableOpacity onPress={()=>this.props.navigator.replaceAtIndex({component: MySecondPage}, 2)}> // <Text>返回到第二頁</Text> // </TouchableOpacity> // <TouchableOpacity onPress={()=>this.props.navigator.resetTo({component: FirstPage})}> // <Text>返回到第一頁</Text> // </TouchableOpacity> // <TouchableOpacity onPress={()=>this.props.navigator.resetTo({component: MySecondPage})}> // <Text>返回到第二頁</Text> // </TouchableOpacity> // <TouchableOpacity onPress={()=>this.props.navigator.popToTop()}> // <Text>返回到第一頁</Text> // </TouchableOpacity> componentWillUnmount(){ console.log('MyThirdPage-componentWillUnmount'); } render(){ return( <View style={{marginTop: 60,flex:1,justifyContent: 'center',alignItems: 'center',}}> <Text>{'third Page'}</Text> <TouchableOpacity onPress={()=>this.props.navigator.replace({component: FirstPage})}> <Text>返回到第一頁</Text> </TouchableOpacity> </View> ) } }
下面是一個查詢用戶信息的例子,FirstPage傳遞id到MySecondPage,而後MySecondPage返回user信息給FirstPage。FirstPage:
import React, { Component } from 'react'; import { View, Navigator } from 'react-native'; import MySecondPage from './MySecondPage'; export default class FirstPage extends Component { constructor(props) { super(props); this.state = { id: 2, user: null, } } pressButton() { if(this.props.navigator) { this.props.navigator.push({ name: 'MySecondPage', component: MySecondPage, params: { id: this.state.id, //從MySecondPage獲取user getUser: (myUser) => { this.setState({ user: myUser }) } } }); } } render() { if(this.state.user) { return( <View> <Text>用戶信息: { JSON.stringify(this.state.user) }</Text> </View> ); }else { return( <View> <TouchableOpacity onPress={this.pressButton.bind(this)}> <Text>查詢ID爲{ this.state.id }的用戶信息</Text> </TouchableOpacity> </View> ); } } }
MySecondPage:
const myObj = { 1: { name: 'user1', age: 25 }, 2: { name: 'user2', age: 26 } }; import React from 'react'; import { View, Navigator } from 'react-native'; import FirstPage from './FirstPage'; export default class MySecondPage extends React.Component { constructor(props) { super(props); this.state = { id: null } } componentDidMount() { //這裏獲取從FirstPage傳遞過來的參數: id this.setState({ id: this.props.id }); } pressButton() { const { navigator } = this.props; if(this.props.getUser) { let user = myObj[this.props.id]; this.props.getUser(user); } if(navigator) { navigator.pop(); } } render() { return( <View> <Text>得到的參數: id={ this.state.id }</Text> <TouchableOpacity onPress={this.pressButton.bind(this)}> <Text>點我跳回去</Text> </TouchableOpacity> </View> ); } }
下面是一個登錄頁和歡迎頁的例子。
MyFirstApp.js:
import React, { Component } from 'react'; import { AppRegistry, Text, View, Navigator, TouchableOpacity, Platform } from 'react-native'; import Splash from './Splash'; const defaultRoute = { component: Splash }; export default class myFirstApp extends Component { _renderScene(route, navigator) { let Component = route.component; return ( <Component {...route.params} navigator={navigator} /> ); } _renderNavBar() { const styles = { title: { flex: 1, alignItems: 'center', justifyContent: 'center' }, button: { flex: 1, width: 50, alignItems: 'center', justifyContent: 'center' }, buttonText: { fontSize: 18, color: '#FFFFFF', fontWeight: '400' } } var routeMapper = { LeftButton(route, navigator, index, navState) { if(index > 0) { return ( <TouchableOpacity onPress={() => navigator.pop()} style={styles.button}> <Text style={styles.buttonText}>Back</Text> </TouchableOpacity> ); } else { return ( <TouchableOpacity onPress={() => navigator.pop()} style={styles.button}> <Text style={styles.buttonText}>Logo</Text> </TouchableOpacity> ); } }, RightButton(route, navigator, index, navState) { if(index > 0 && route.rightButton) { return ( <TouchableOpacity onPress={() => navigator.pop()} style={styles.button}> <Text style={styles.buttonText}></Text> </TouchableOpacity> ); } else { return null } }, Title(route, navigator, index, navState) { return ( <View style={styles.title}> <Text style={styles.buttonText}>{route.title ? route.title : 'Splash'}</Text> </View> ); } }; return ( <Navigator.NavigationBar style={{ alignItems: 'center', backgroundColor: '#55ACEE', shadowOffset:{ width: 1, height: 0.5, }, shadowColor: '#55ACEE', shadowOpacity: 0.8, }} routeMapper={routeMapper} /> ) } render() { return ( <View style={{height:200}}> <Navigator initialRoute={defaultRoute} renderScene={this._renderScene} sceneStyle={{paddingTop: (Platform.OS === 'android' ? 66 : 74)}} navigationBar={this._renderNavBar()} /> </View> ); } } }); AppRegistry.registerComponent('myFirstApp', () => myFirstApp);
Splash.js:
import React, { Component } from 'react'; import { View, Text, TouchableOpacity } from 'react-native'; import Login from './Login'; class Splash extends Component { _openPage() { this.props.navigator.push({ title: 'Login', component: Login }) } render() { return ( <View style={{ flex: 1, alignItems: 'center', backgroundColor: '#FFFFFF' }}> <Text>Splash Page</Text> <TouchableOpacity onPress={this._openPage.bind(this)}> <Text style={{ color: '#55ACEE' }}>Open New Page</Text> </TouchableOpacity> </View> ); } } export default Splash;
Login.js:
import React, { Component } from 'react'; import {View, Text, TextInput, TouchableOpacity } from 'react-native'; import Welcome from './Welcome'; class Login extends Component { constructor(props) { super(props); this.state = { name: null, age: null, } } _openPage() { this.props.navigator.push({ component: Welcome, params: { name: this.state.name, age: this.state.age, changeMyAge: (age) => { this.setState({ age }) } } }) } render() { return ( <View style={{ flex: 1, alignItems: 'center', backgroundColor: '#FFFFFF' }}> <Text>Form Page</Text> <TextInput value={this.state.name} onChangeText={name => this.setState({ name })} placeholder={'Enter your name'} style={{ height: 40, width: 200 }} /> <Text>My age: {this.state.age ? this.state.age : 'Unknown'}</Text> <TouchableOpacity onPress={this._openPage.bind(this)}> <Text style={{ color: '#55ACEE' }}>Update my age</Text> </TouchableOpacity> </View> ); } } export default Login;
Welcome.js:
import React, { Component } from 'react'; import { TextInput, View, Text, TouchableOpacity } from 'react-native'; class Welcome extends Component { _back() { this.props.navigator.pop(); } render() { return ( <View style={{ flex: 1, alignItems: 'center', backgroundColor: '#FFFFFF' }}> <Text>Welcome Page</Text> <Text>Welcome to Navigation! {this.props.name}</Text> <TextInput onChangeText={age => this.props.changeMyAge(age) } placeholder={'Enter your age:'} style={{ height: 40, width: 200 }} /> <TouchableOpacity onPress={this._back.bind(this)}> <Text style={{ color: '#55ACEE' }}>Save my age</Text> </TouchableOpacity> </View> ); } } export default Welcome;
實例化
首次實例化
getDefaultProps getInitialState componentWillMount render componentDidMount
實例化完成後的更新
getInitialState componentWillMount render componentDidMount
存在期
組件已存在時的狀態改變
componentWillReceiveProps shouldComponentUpdate componentWillUpdate render componentDidUpdate
銷燬&清理期
componentWillUnmount
說明
生命週期共提供了10個不一樣的API。
1.getDefaultProps
做用於組件類,只調用一次,返回對象用於設置默認的props,對於引用值,會在實例中共享。
2.getInitialState
做用於組件的實例,在實例建立時調用一次,用於初始化每一個實例的state,此時能夠訪問this.props。
3.componentWillMount
在完成首次渲染以前調用,此時仍能夠修改組件的state。
4.render
必選的方法,建立虛擬DOM,該方法具備特殊的規則:
只能經過this.props和this.state訪問數據
能夠返回null、false或任何React組件
只能出現一個頂級組件(不能返回數組)
不能改變組件的狀態
不能修改DOM的輸出
5.componentDidMount
真實的DOM被渲染出來後調用,在該方法中可經過this.getDOMNode()訪問到真實的DOM元素。此時已可使用其餘類庫來操做這個DOM。
在服務端中,該方法不會被調用。
6.componentWillReceiveProps
組件接收到新的props時調用,並將其做爲參數nextProps使用,此時能夠更改組件props及state。
componentWillReceiveProps: function(nextProps) { if (nextProps.bool) { this.setState({ bool: true }); } }
7.shouldComponentUpdate
組件是否應當渲染新的props或state,返回false表示跳事後續的生命週期方法,一般不須要使用以免出現bug。在出現應用的瓶頸時,可經過該方法進行適當的優化。
在首次渲染期間或者調用了forceUpdate方法後,該方法不會被調用
8.componentWillUpdate
接收到新的props或者state後,進行渲染以前調用,此時不容許更新props或state。
9.componentDidUpdate
完成渲染新的props或者state後調用,此時能夠訪問到新的DOM元素。
10.componentWillUnmount
組件被移除以前被調用,能夠用於作一些清理工做,在componentDidMount方法中添加的全部任務都須要在該方法中撤銷,好比建立的定時器或添加的事件監聽器。
import React, { Component, PropTypes } from 'react'; import { Text, View, TouchableOpacity } from 'react-native'; export default class MyPropType extends Component { constructor(props){ super(props); this.state = { stateName: this.props.myName + ',xhh', count: 0, } console.log('init-constructor'); } static propTypes = { myName: PropTypes.string, age: PropTypes.number, sex: PropTypes.string.isRequired } static get defaultProps() { return { myName: "xhh", age: 18 } } doUpdateCount(){ this.setState({ count: this.state.count+1 }) } componentWillMount() { console.log('componentWillMount'); } componentDidMount() { console.log('componentDidMount') } componentWillReceiveProps(nextProps){ console.log('componentWillReceiveProps') } shouldComponentUpdate(nextProps, nextState){ console.log('shouldComponentUpdate'); // return nextProps.id !== this.props.id; if(nextState.count > 10) return false; return true; } componentWillUpdate(){ console.log('componentWillUpdate'); } componentDidUpdate(){ console.log('componentDidUpdate'); } componentWillUnmount(){ console.log('componentWillUnmount'); } render(){ console.log('render'); return ( <View> <Text>姓名:{this.props.myName}</Text> <Text>別名:{this.state.stateName}</Text> <Text>年齡:{this.props.age}</Text> <Text>性別:{this.props.sex}</Text> <Text>父元素計數是:{this.state.count}</Text> <TouchableOpacity onPress={ this.doUpdateCount.bind(this) } style={{ padding: 5,backgroundColor: '#ccc' }}> <Text>點我開始計數</Text> </TouchableOpacity> <SubMyPropType count1={this.state.count} /> </View> ) } } class SubMyPropType extends Component { componentWillReceiveProps(nextProps){ console.log('subMyPropType-componentWillReceiveProps') } shouldComponentUpdate(nextProps, nextState){ console.log('subMyPropType-shouldComponentUpdate'); // return nextProps.id !== this.props.id; if(nextProps.count1 > 5) return false; return true; } componentWillUpdate(){ console.log('subMyPropType-componentWillUpdate'); } componentDidUpdate(){ console.log('subMyPropType-componentDidUpdate'); } componentWillUnmount(){ console.log('subMyPropType-componentWillUnmount'); } render(){ console.log('subMyPropType-render'); return( <Text>子元素計數是:{this.props.count1}</Text> ) } } // init-constructor // componentWillMount // render // subMyPropType-render // componentDidMount //子元素和父元素都在計時 // shouldComponentUpdate // componentWillUpdate // render // subMyPropType-componentWillReceiveProps // subMyPropType-shouldComponentUpdate // subMyPropType-componentWillUpdate // subMyPropType-render // subMyPropType-componentDidUpdate // componentDidUpdate //子元素中止計時(count1 > 5) // shouldComponentUpdate // componentWillUpdate // render // subMyPropType-componentWillReceiveProps // subMyPropType-shouldComponentUpdate // componentDidUpdate //父元素也中止計時 // shouldComponentUpdate // 生命週期 調用次數 可否使用setSate() // getDefaultProps 1(全局調用一次) 否 // getInitialState 1 否 // componentWillMount 1 是 // render >=1 否 // componentDidMount 1 是 // componentWillReceiveProps >=0 是 // shouldComponentUpdate >=0 否 // componentWillUpdate >=0 否 // componentDidUpdate >=0 否 // componentWillUnmount 1 否