1.Hello world
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);
2.Props(属性)
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> ) } }
3.State(状态)
在constructor中初始化state,然后在需要修改时调用setState方法。
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>
4.样式
<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',});
5.高度与宽度
(1)指定宽高
React Native中的尺寸都是无单位的,表示的是与设备像素密度无关的逻辑像素点。
<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)宽高
使用flex:1来指定某个组件扩张以撑满所有剩余的空间。如果有多个并列的子组件使用了flex:1,则这些子组件会平分父容器中剩余的空间。如果这些并列的子组件的flex值不一样,则谁的值更大,谁占据剩余空间的比例就更大。
组件能够撑满剩余空间的前提是其父容器的尺寸不为零。如果父容器既没有固定的width和height,也没有设定flex,则父容器的尺寸为零。其子组件如果使用了flex,也是无法显示的。
<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%的设置,所以如果需要让元素撑满屏幕,需要:
import { Dimensions,View } from 'react-native'; <View style={{width: Dimensions.get('window').width,height: Dimensions.get('window').height}} />
6.使用FlexBox布局
flexDirection
的默认值是column而不是row,flex也只能指定一个数字值。
flexDirection可以决定布局的主轴。子元素是应该沿着水平轴(row
)方向排列,还是沿着竖直轴(column
)方向排列呢?默认值是竖直轴(column)方向。justifyContent
可以决定其子元素沿着主轴的排列方式。子元素是应该靠近主轴的起始端还是末尾段分布呢?亦或应该均匀分布?对应的这些可选项有:flex-start,center,flex-end,space-around以及space-between
。alignItems
可以决定其子元素沿着次轴(与主轴垂直的轴,比如若主轴方向为row,则次轴方向为column)的排列方式。子元素是应该靠近次轴的起始端还是末尾段分布呢?亦或应该均匀分布?对应的这些可选项有:flex-start,flex-end以及stretch
。
<View style={{ flex: 1,flexDirection: 'column',justifyContent: 'center',alignItems: 'center',}}> <View style={{width: 50,backgroundColor: 'powderblue'}} /> <View style={{width: 50,backgroundColor: 'skyblue'}} /> <View style={{width: 50,backgroundColor: 'steelblue'}} /> </View>
7.处理文本输入
TextInput
是一个允许用户输入文本的基础组件。它有一个名为onChangeText
的属性,此属性接受一个函数,而此函数会在文本变化时被调用。另外还有一个名为onSubmitEditing
的属性,会在文本被提交后(用户按下软键盘上的提交键)调用(注意react
中的onChange
对应的是rn中的onChangeText
)。
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> ); }
8.ScrollView
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,backgroundColor: colorList[i] }}></View>; scrollViewList.push(ViewItem); } console.log(scrollViewList); return scrollViewList; } render(){ return ( <ScrollView horizontal={true}> { this.getScrollViewList() } </ScrollView> ) } }
如果页面内容一屏展示不完,需要滚动观看那就可以使用ScrollView
了。
9.ListView
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,marginTop: 5,marginBottom: 5 }}> <ListView dataSource={this.state.dataSource} renderRow={(myRowData) => <Text>{myRowData}</Text>} /> </View> ); } }
10.网络
import React,{ Component } from 'react'; import { TouchableOpacity,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> ); } }
11.路由Navigator
导航方法:
如果你得到了一个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
(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',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,}}> <Text>{'first Page'}</Text> <TouchableOpacity onPress={()=>this.onPressButton()}> <Text>点击跳转到第二页</Text> </TouchableOpacity> </View> ) } }
navigatorPage.js:
import React,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,}}> <Text>{'second Page'}</Text> <TouchableOpacity onPress={()=>this.onPressButton()}> <Text>点击跳转到第三页</Text> </TouchableOpacity> </View> ) } }
navigatorOtherPage.js:
import React,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,}}> <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,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,justifyContent: 'center' },button: { flex: 1,width: 50,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,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,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,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,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,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,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,TouchableOpacity } from 'react-native'; class Welcome extends Component { _back() { this.props.navigator.pop(); } render() { return ( <View style={{ flex: 1,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;
12.组件生命周期
实例化
首次实例化
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,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 否