1. 程式人生 > >React-navigation之StackNavigator

React-navigation之StackNavigator

1 先給出資料:

   參考:資料一資料二 有問題找 issues, 基本上坑都在這裡。

2 導航欄分類

按使用形式主要分三部分:

(1) StackNavigator: 類似於普通的Navigator,實現不同的頁面進行跳轉
(2) TabNavigator: 相當於裡面的TabBarController,螢幕上方的標籤欄,不同的tabs互相切換。
(3) DrawerNavigator: 抽屜效果,側邊滑出

今天主要學習StackNavigator,另外兩個隨後跟上。

3  navigationOptions 

在這一塊我是狠狠的被坑了一把,資料上給出的navigationOptions是這樣的:

  • title: 導航欄的標題

  • header: 導航欄設定物件

    • visible: 導航欄是否顯示
    • title: 導航欄的標題, 可以是字串也可以是個元件
    • backTitle: 左上角的返回鍵文字, 預設是上一個頁面的title
    • right: 導航欄右按鈕
    • left: 導航欄左按鈕
    • style: 導航欄的style
    • titleStyle: 導航欄的title的style
    • tintColor: 導航欄顏色
  • cardStack: 配置card stack

    • gesturesEnabled: 是否允許右滑返回,在iOS上預設為true,在Android上預設為false

      按照說明設定各種屬性,結果是各種無效,查詢資料也沒有找到好的例項,好吧,還是回來看官方文件,哎,才發現navigationOptions變樣了,可能是版本更新了或編輯器的問題的,在這裡我用的編輯器是Sublime Text,反正是各種無效,我們來看官網的

navigationOptions:

  • title: 導航欄的標題

  • header: 導航欄設定物件

  • headerTitle: 導航欄的標題, 可以是字串也可以是個元件
  • headerBackTitle: 左上角的返回鍵文字, 預設是上一個頁面的title,設定這個屬性會覆蓋掉title的值
  • headerRight: 導航欄右按鈕
  • headerLeft: 導航欄左按鈕
  • headerStyle: 導航欄的style
  • headerTitleStyle: 導航欄的title的style
  • headerTintColor: 返回按鈕的顏色
  • headerPressColorAndroid :按壓返回按鈕顯示的顏色 安卓系統 >= 5.0才有效。
  • gesturesEnabled :是否允許右滑返回,在iOS上預設為true,在Android上預設為false

使用事例:

ChatScreen.navigationOptions = ({navigation}) => {
	console.log("---------navigation------------>");
    console.log(navigation);
    //Object {state: Object, dispatch: function, goBack: function, navigate: function, setParams: function}
	return {
         // 展示資料 "`" 不是單引號 
         title: `Chat with ${navigation.state.params.user}`,
         // 導航欄的標題, 可以是字串也可以是個元件 會覆蓋 title 的值 
         // headerTitle : '返回',
         //右邊按鈕
         headerRight:(  
         	<View>
                <Button  
                   title="點我" 
                   onPress={() => alert("hello")}  
                />  
         	</View>   
        ),
         //左上角的返回鍵文字, 預設是上一個頁面的title  IOS 有效
         headerBackTitle : "返回",
            //導航欄的style
         headerStyle: {
                backgroundColor: '#fff'
            },
            //導航欄的title的style
         headerTitleStyle: {
                color: 'green',
                //居中顯示
                alignSelf : 'center',
         },
         //按壓返回按鈕顯示的顏色 API > 5.0 有效
         headerPressColorAndroid : 'blue',
         //返回按鈕的顏色
         headerTintColor : 'red',
         //是否允許右滑返回,在iOS上預設為true,在Android上預設為false
         gesturesEnabled: true,
	};
  	   
};

4  StackNavigatorConfig

引數:

  • initialRouteName: 設定預設的頁面元件,必須是上面已註冊的頁面元件
  • initialRouteParams: 初始路由的引數
  • navigationOptions: 螢幕導航的預設選項
  • paths: RouteConfigs裡面路徑設定的對映

  • mode: 頁面切換模式:

    • card: 普通app常用的左右切換
    • modal: 上下切換
  • headerMode: 導航欄的顯示模式:

    • float: 無透明效果, 預設
    • screen: 有漸變透明效果, 如微信QQ的一樣
    • none: 隱藏導航欄
  • cardStyle: 樣式

  • onTransitionStart: 頁面切換開始時的回撥函式

  • onTransitionEnd: 頁面切換結束時的回撥函式

這個到沒有什麼變化。

5 API

StackNavigator(RouteConfigs, StackNavigatorConfig)

引數一:配置你需要跳轉的導航介面,引數二:可選,配置屬性(參見4)。

例:

// MyFirstProject 是你的react native 專案名  注意: 這塊程式碼要放置到HomeScreen,ChatScreen...的下面否則會出錯:Home不存在。
const MyFirstProject = StackNavigator({
  Home: { screen: HomeScreen },
  Chat: { screen: ChatScreen },
  // navigationOptions: {}  // 此處設定了, 會覆蓋元件內的`static navigationOptions`設定. 
},{
	initialRouteName: 'Home', // 預設顯示介面
	  //導航欄相關設定項
    // header:{
    // 	    //導航欄可見
    //         visible : false,
    //         //左上角的返回鍵文字, 預設是上一個頁面的title
    //         backTitle : "返回",
    //         //導航欄的style
    //         headerStyle: {
    //             backgroundColor: '#fff'
    //         },
    //         //導航欄的title的style
    //         titleStyle: {
    //             color: 'green'
    //         }
    // },
    // title : 'home',
    // //導航欄的style
    //  headerStyle: {
    //             backgroundColor: '#fff'
    //  },
    //         //導航欄的title的style
    //  headerTitleStyle: {
    //          color: 'blue',
    //          //居中顯示
    //          alignSelf : 'center',
    //      },

    // //是否允許右滑返回,在iOS上預設為true,在Android上預設為false
    // cardStack: {
    //         gesturesEnabled: true,
    // },
    onTransitionStart: ()=>{ console.log('導航欄切換開始'); },  // 回撥
    onTransitionEnd: ()=>{ console.log('導航欄切換結束'); },  // 回撥
});

6 資料傳遞分析

import React from 'react';
import {
  AppRegistry,
  Text,
  View,
  Button,
} from 'react-native';
import { StackNavigator } from 'react-navigation';


//第一個頁面
class HomeScreen extends React.Component {
  // static navigationOptions = {
  // 	//標題
  //   title: 'FirstScreen',
  //    //是否允許右滑返回,在iOS上預設為true,在Android上預設為false
  //   cardStack: {
  //           gesturesEnabled: true,
  //   },

  // };

  render() {
  	const { navigate } = this.props.navigation;
  	// navigate 是什麼鬼 就是下面的這塊程式碼 可見 navigate 是個function物件 引數一 是要跳轉的頁面名字 例如:Chat 引數2:要傳遞的引數 引數3: 一般不用
  	// function navigate(routeName, params, action) {
   //    return navigation.dispatch(_NavigationActions2.default.navigate({
   //      routeName: routeName,
   //      params: params,
   //      action: action
   //    }));
  	console.log(navigate);
    return (
    	<View>
            <Text>Hello, Navigation!</Text>
            <Text></Text>
           <Button
              //點選跳轉到介面二,並傳遞引數 { user: 'Lucy' }
              onPress={() => navigate('Chat', { user: 'Lucy' })}
              title="去 ChatScreen介面"
           />
           <Text></Text>
    	</View>
    );
  }
}

// // 這樣也是可以
// HomeScreen.navigationOptions = {
//   	//標題
//     title: 'FirstScreen',
//      //是否允許右滑返回,在iOS上預設為true,在Android上預設為false
//     cardStack: {
//             gesturesEnabled: true,
//     },

//  };

// 第二個頁面
class ChatScreen extends React.Component {

  static navigationOptions = ({navigation}) => ({
  	// 展示資料 "`" 不是單引號 
    title: `Chat with ${navigation.state.params.user}`,
    
  });

  render() {

  	// The screen's current route is passed in to `props.navigation.state`: 傳過來的物件:{ user: 'Lucy' }
    const { params } = this.props.navigation.state;
    console.log(this.props.navigation);
    //object {state: Object, dispatch: function, goBack: function, navigate: function, setParams: function}
    console.log(this.props.navigation.state);
    //Object {params: Object, key: "id-1498014888408-1", routeName: "Chat"}
    console.log("-----------params----------->");
    console.log(params);
    //列印結果{user: "Lucy"}
    return (
      <View>
        <Text>Chat with {params.user}</Text>
      </View>
    );
  }
}

ChatScreen.navigationOptions = ({navigation}) => {
	console.log("---------navigation------------>");
    console.log(navigation);
    //Object {state: Object, dispatch: function, goBack: function, navigate: function, setParams: function}
	return {
         // 展示資料 "`" 不是單引號 
         title: `Chat with ${navigation.state.params.user}`,
         // 導航欄的標題, 可以是字串也可以是個元件 會覆蓋 title 的值 
         // headerTitle : '返回',
         //右邊按鈕
         headerRight:(  
         	<View>
                <Button  
                   title="點我" 
                   onPress={() => alert("hello")}  
                />  
         	</View>   
        ),
         //左上角的返回鍵文字, 預設是上一個頁面的title  IOS 有效
         headerBackTitle : "返回",
            //導航欄的style
         headerStyle: {
                backgroundColor: '#fff'
            },
            //導航欄的title的style
         headerTitleStyle: {
                color: 'green',
                //居中顯示
                alignSelf : 'center',
         },
         //按壓返回按鈕顯示的顏色 API > 5.0 有效
         headerPressColorAndroid : 'blue',
         //返回按鈕的顏色
         headerTintColor : 'red',
         //是否允許右滑返回,在iOS上預設為true,在Android上預設為false
         gesturesEnabled: true,
	};
  	   
};

// MyFirstProject 是你的react native 專案名  注意: 這塊程式碼要放置到HomeScreen,ChatScreen...的下面否則會出錯:Home不存在。
const MyFirstProject = StackNavigator({
  Home: { screen: HomeScreen },
  Chat: { screen: ChatScreen },
  // navigationOptions: {}  // 此處設定了, 會覆蓋元件內的`static navigationOptions`設定. 
},{
	initialRouteName: 'Home', // 預設顯示介面
	  //導航欄相關設定項
    // header:{
    // 	    //導航欄可見
    //         visible : false,
    //         //左上角的返回鍵文字, 預設是上一個頁面的title
    //         backTitle : "返回",
    //         //導航欄的style
    //         headerStyle: {
    //             backgroundColor: '#fff'
    //         },
    //         //導航欄的title的style
    //         titleStyle: {
    //             color: 'green'
    //         }
    // },
    // title : 'home',
    // //導航欄的style
    //  headerStyle: {
    //             backgroundColor: '#fff'
    //  },
    //         //導航欄的title的style
    //  headerTitleStyle: {
    //          color: 'blue',
    //          //居中顯示
    //          alignSelf : 'center',
    //      },

    // //是否允許右滑返回,在iOS上預設為true,在Android上預設為false
    // cardStack: {
    //         gesturesEnabled: true,
    // },


    onTransitionStart: ()=>{ console.log('導航欄切換開始'); },  // 回撥
    onTransitionEnd: ()=>{ console.log('導航欄切換結束'); },  // 回撥
});

AppRegistry.registerComponent('MyFirstProject', () => MyFirstProject);

       先說明下流程第一個介面HomeScreen跳轉到第二個介面ChatScreen,然後可以返回到第一介面,在這裡想要說的有兩個重點:(1) title:`Chat with${navigation.state.params.user}` 注意“`”不是單引號,是和“~”在同一個按鍵的字元。(2)從第一個介面到第二介面引數是如何傳遞過去的,看下面的分析:

在HomeScreen介面中,通過const { navigate } =this.props.navigation 獲取物件 navigate,那麼navigate是個什麼東西?來看下列印結果:

function navigate(routeName, params, action) {
    return navigation.dispatch(_NavigationActions2.default.navigate({
        routeName: routeName,
        params: params,
        action: action
}));

    不用意外navigate就是一個函式物件,引數一:需要跳轉的介面(是在StackNavigator{}中宣告的導航介面【例chat】),引數二:需要傳遞的資料(例{ user:'Lucy' }),引數三:處理資料或跳轉的action (在這裡先不管他)。

因此在下面我們使用到了:()=> navigate('Chat', { user:'Lucy' }) 跳轉到ChatSrceen介面,並把{ user:'Lucy' }傳遞過去。

   我們再來看看ChatSrceen是如果接受資料的,在ChatScreen中通過

const { params } =this.props.navigation.state獲取資料,列印下params是?結果:{ user:'Lucy' },

那麼this.props.navigation.state 中為什麼會存在物件{ user:'Lucy' },那麼我們再列印下this.props.navigation,結果:


好吧,在這裡this.props.navigation 變成了一個真正的物件了,而不是函數了,可以看到這個物件中有個屬性state,且屬性state也是個物件,那麼它的內容呢?如下:


很顯然物件state中又有物件params,而params就是我們要找的資料{ user:'Lucy' }。這也是資料傳遞的過程,至於為什麼在HomeScreen中this.propes.navigation是個函式,而到了ChatScreen變成了真正的物件(我們需要的)了,其實上面是把this.props.navigation.navigate 賦值了給{ navigate }

下面是總的列印結果(方便對比):