react-navigation的StackNavigator实现页面跳转

简介

对于React Navigation它里面包括以下控件:

  • StackNavigator :用于app界面窗口之间的切换
  • TabNavigator :用于设置一个界面的不同tabs
  • DrawerNavigator :用于抽屉界面

他们每一个都是项目中频繁使用的,我们要对他们一一进行学习

1、安装react-navigation

使用命令npm i react-navigation --save,就可以安装react-navigation了

WX20181108-161859.png

StackNavigator API

StackNavigator(RouteConfigs,StackNavigatorConfig)

  • RouteConfigs(必选):路由配置对象是从路由名称到路由配置的映射,告诉导航器该路由呈现什么。
  • StackNavigatorConfig(可选):配置导航器的路由(如:默认首屏,navigationOptions,paths等)样式(如,转场模式mode、头部模式等)。

从StackNavigator API上可以看出StackNavigator支持通过RouteConfigs和StackNavigatorConfig两个参数来创建StackNavigator导航器。

RouteConfigs

RouteConfigs支持三个参数screen、path以及navigationOptions;

  • screen(必选):指定一个React组件作为屏幕的主要显示内容,当这个组件被StackNavigator加载时,它会被分配一个navigation prop。
  • path(可选):用来设置支持schema跳转时使用,具体使用会在下文的又不安Schema章节中讲到;
  • navigationOptions(可选):用以配置全局的屏幕导航选项如:title、headerRight、headerLeft等;

StackNavigatorConfig

react-navigation源码中可以看出StackNavigatorConfig支持配置的参数有10个

export type NavigationStackRouterConfig={
    initialRouteName?:string,
    initialRouteParams?:NavigationParams,
    paths?:NavigationPathsConfig,
    navigationOptions?:NavigationScreenConfig<*>,
};
export type NavigationStackViewConfig={
    mode?:'card'|'modal',
    headerMode?HeaderMode,
    cardStyle?:ViewStyleProp,
    transitionConfig?:()=>TransitionConfig,
    onTransitionStart?:()=>void,
    onTransitionEnd?:()=>void,
};

这10个参数可以根据作用不同分为路由配置、视图样式配置两类,首先看用于路由配置的参数:

用于路由配置的参数:

  • initialRouteName:设置默认的页面组件,必须是上面已注册的页面组件。
  • initialRouteParams:初始路由的参数。
  • navigationOptions:屏幕导航的默认选项,下文会详细讲解。
  • paths:用来设置支持schema跳转时使用,具体使用会在下文的有关Schema章节中讲到。

用于导航样式配置的参数:

  • mode:页面切换模式:左右是card(相当于IOS中的push效果),上下是modal(相当于IOS中的modal效果)
    • card:普通app常用的左右切换。
    • modal:上下切换
  • headerMode:导航栏的显示模式:screen:有渐变透明效果,float:无透明效果,none:隐藏导航栏。
    • float:无透明效果,默认。
    • screen:有渐变透明效果,如微信QQ的一样。
    • none:隐藏导航栏。
  • cardStyle:样式(IOS上页面切换会有白色渐变蒙层,想去掉则可以这样设置,cardStyle:{opacity:null},切换页面时的页面边框也在这里可以设置)。
  • onTransitionStart:页面切换开始时的回调函数(我们可以在这里注册一些通知,告诉我们切面切换的状态,方便后面处理页面切换事件)。
  • onTransitionEnd:页面切换结束时的回调函数。

navigationOptions(屏幕导航选项)

支持以下参数:

  • title:可以作为headerTitle的备选字段(当没设置headerTitle时会用该字段作为标题),也可以作为TabNavigator的tabBarLabel以及DrawerNavigator的drawerLabel。
  • header:自定义导航条,可以通过设置null来隐藏导航条;
  • headerTitle:标题;
  • headerTitleAllowFontScaling:标题是否允许缩放,默认true;
  • headerBackTitle:定义在IOS上当前页面进入到下一页面的回退标题,可以通过设置null来禁用它;
  • headerTruncatedBackTitle:当回退标题不能显示的时候显示此属性的标题,比如回退标题太长了;
  • headerRight:定义导航栏右边视图;
  • headerLeft:定义导航栏左边视图;
  • headerStyle:定义导航栏的样式,比如背景色等;
  • headerTitleStyle:定义标题的样式;
  • headerBackTitleStyle:定义返回标题的样式;
  • headerTintColor:定义导航条的tintColor,会覆盖headerTitleStyle中的颜色;
  • gesturesEnabled:定义是否能侧滑返回,IOS默认true,Android默认false;
  • gestureResponseDistance:定义滑动返回的有效距离,水平状态下默认:25,垂直状态默认135;
  • gestureDirection:设置关闭手势的方向。默认从左向右,可以设置从右到左的滑动操作。

Screen Navigation Prop(屏幕的navigation Prop)

当导航器中的屏幕被打开时,它会收到一个navigation prop,navigation prop是整个导航环节的关键一员,接下来就详细讲解一下navigation的作用。

navigation包含一下功能:

  • navigate:跳转到其他界面;
  • state:屏幕的当前state;
  • setParams:改变路由的params;
  • goBack:关闭当前屏幕;
  • dispatch:向路由发送一个action;

使用navigate进行界面之间的跳转

  • navigate(routeName, params, action)
export const AppStackNavigator = StackNavigator({
    HomeScreen: {
        screen: HomeScreen
    },
    Page1: {
        screen: Page1
    })

class HomeScreen extends React.Component {
  render() {
    const {navigate} = this.props.navigation;

    return (
      <View>
        <Text>This is HomeScreen</Text>
        <Button
          onPress={() => navigate('Page1', {name: 'Devio'})}
          title="Go to Page1"
        />
      </View>
     )
   }
}

使用goBack返回到上一页面或指定页面

  • goBack: function goBack(key):我们可以借助goBack返回到上一页或者路由栈的指定页面。
  • 其中key表示你要返回到页面的页面标识如id-1517035332238-4,不是routeName。
  • 可以通过指定页面的navigation.state.key来获得页面的标识。
  • key非必传,也可传null。

navigation.state {params: {…}, key: "id-1517035332238-4", routeName: "Page1"}

export default class Page1 extends React.Component {
    render() {
        const {navigation} = this.props;
        return <View style=>
            <Text style={styles.text}>欢迎来到Page1</Text>
            <Button
                title="Go Back"
                onPress={() => {
                    navigation.goBack();
                }}
            />
        </View> 
    }
}

具体代码实现

  • routeName:要跳转到的界面的路由名,也就是在导航其中配置的路由名;
  • params:要传递给下一个界面的参数;
  • action:如果该界面是一个navigator的话,将运行这个sub-action。

创建几个页面,HomePage、Page1和Page2,然后实现他们的跳转

HomePage的代码

import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View, Button, Alert} from 'react-native';

type Props = {};
export default class HomePage extends Component<Props> {
    render() {
        //从props里面取得navigation
        const {navigation} = this.props;
        return (
            <View style={styles.container}>
                <Text style={styles.welcome}>Welcome to HomePage!</Text>
                <Button
                    title="跳转到Page1"
                    onPress={() => {
                        navigation.navigate('Page1')
                    }}/>

                <View style={{marginTop: 10}}>
                    <Button
                        title="跳转到Page2"
                        onPress={() => {
                            navigation.navigate('Page2')
                        }}/>
                </View>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
    },
    welcome: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
    },
    instructions: {
        textAlign: 'center',
        color: '#333333',
        marginBottom: 5,
    },
});

Page1的代码

import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View,Button,Alert} from 'react-native';

export default class Page1 extends Component {
    render() {
        //从props里面取得navigation
        const {navigation} =this.props;

        return (
            <View style={styles.container}>
                <Text style={styles.welcome}>Welcome to Page1!</Text>
                <Button
                    title="Go Back"
                    onPress={()=>{
                        //返回上一页
                        navigation.goBack();
                    }}/>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
    },
    welcome: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
    },
    instructions: {
        textAlign: 'center',
        color: '#333333',
        marginBottom: 5,
    },
});

Page2的代码

import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View,Button,Alert} from 'react-native';

export default class Page1 extends Component {
    render() {
        //从props里面取得navigation
        const {navigation} =this.props;

        return (
            <View style={styles.container}>
                <Text style={styles.welcome}>Welcome to Page2!</Text>
                <Button
                    title="Go Back"
                    onPress={()=>{
                        //返回上一页
                        navigation.goBack();
                    }}/>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
    },
    welcome: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
    },
    instructions: {
        textAlign: 'center',
        color: '#333333',
        marginBottom: 5,
    },
});

最后需要创建一个导航器AppStackNavigator

import {StackNavigator} from 'react-navigation';
import HomePage from '../pages/HomePage';
import Page1 from '../pages/Page1';
import Page2 from '../pages/Page2';

/**
 * 导航器
 */
export const AppStackNavigator = StackNavigator({
    HomePage: {
        screen: HomePage
    },
    Page1: {
        screen: Page1
    },
    Page2: {
        screen: Page2
    }
})

最后在App中导入导航器AppStackNavigator,这样就可以运行起来了

WX20181108-162735.png

这样就可以实现HomePage、Page1和Page2这几个页面的跳转了

1.gif

上面这几个页面默认都是有导航栏的,如果想去掉,则可以在导航器(AppStackNavigator)中设置

禁掉全局的导航栏

export const AppStackNavigator = StackNavigator({
    HomePage: {
        screen: HomePage
    },
    Page1: {
        screen: Page1
    },
    Page2: {
        screen: Page2
    }
},{
    //禁掉导航栏,全局作用的
        navigationOptions:{
            header:null
        }
})

禁掉局部的导航栏

export const AppStackNavigator = StackNavigator({
    HomePage: {
        screen: HomePage
    },
    Page1: {
        screen: Page1,
        //禁掉导航栏
        navigationOptions:{
            header:null
        }
    },
    Page2: {
        screen: Page2
    }
})
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352

推荐阅读更多精彩内容