react native入門實例分享

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方法。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>

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中的尺寸都是無單位的,表示的是與設備像素密度無關的邏輯像素點。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}} />

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,center,flex-end以及stretchjson

<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>

7.處理文本輸入

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>
    );
  }

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, height: 150, 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,height: 100,marginTop: 5, marginBottom: 5 }}>
        <ListView
          dataSource={this.state.dataSource}
          renderRow={(myRowData) => <Text>{myRowData}</Text>}
        />
      </View>
    );
  }
}

10.網絡

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>
    );
  }
}

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.jsapp

(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;

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, 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                     否
相關文章
相關標籤/搜索