React-navigation之StackNavigator
1 先給出資料:
參考:資料一、資料二 有問題找 issues, 基本上坑都在這裡。2 導航欄分類
按使用形式主要分三部分:
(1) StackNavigator
:
類似於普通的Navigator,實現不同的頁面進行跳轉
(2) TabNavigator
:
相當於裡面的TabBarController,螢幕上方的標籤欄,不同的tabs互相切換。
(3) DrawerNavigator
:
抽屜效果,側邊滑出
今天主要學習StackNavigator,另外兩個隨後跟上。
3 navigationOptions
在這一塊我是狠狠的被坑了一把,資料上給出的navigationOptions是這樣的:
-
title
: 導航欄的標題 -
header
: 導航欄設定物件visible
: 導航欄是否顯示title
: 導航欄的標題, 可以是字串也可以是個元件backTitle
: 左上角的返回鍵文字, 預設是上一個頁面的titleright
: 導航欄右按鈕left
: 導航欄左按鈕style
: 導航欄的styletitleStyle
: 導航欄的title的styletintColor
: 導航欄顏色
-
cardStack
: 配置card stackgesturesEnabled
: 是否允許右滑返回,在iOS上預設為true,在Android上預設為false
按照說明設定各種屬性,結果是各種無效,查詢資料也沒有找到好的例項,好吧,還是回來看官方文件,哎,才發現navigationOptions變樣了,可能是版本更新了或編輯器的問題的,在這裡我用的編輯器是Sublime Text,反正是各種無效,我們來看官網的
-
title
: 導航欄的標題 -
header
: 導航欄設定物件 - headerTitle: 導航欄的標題, 可以是字串也可以是個元件
- headerBackTitle: 左上角的返回鍵文字, 預設是上一個頁面的title,設定這個屬性會覆蓋掉title的值
- headerRight: 導航欄右按鈕
headerLeft
: 導航欄左按鈕headerStyle
: 導航欄的styleheaderTitleStyle
: 導航欄的title的styleheaderTintColor
: 返回按鈕的顏色- 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 }。
下面是總的列印結果(方便對比):