ReactNative页面跳转Navigator

Stella981
• 阅读 547

ReactNative页面跳转Navigator

Navigator即导航器,通过导航器我们可以实现应用在不同的页面之间进行跳转。 
导航器会建立一个路由栈,用来弹出,推入或者替换路由状态。该路由栈相当于android原生中使用的任务栈。

renderScene

该方法就相当于我们使用的startActivity方法了,我们可以在该方法中设置需要渲染的场景(跳转的页面),该方法接收两个参数(必要参数),route和navigator,其中route就是路由的页面,navigator是一个Navigator对象,因为Navigator对象拥有pop,push,jump等方法,我们需要导航器对象来实现页面的跳转。而路由route需要我们提前进行配置。

我们来看一下renderScene的使用:

    renderScene={(route, navigator) => {
      let Component = route.component;
      return <Component {...route.params} navigator={navigator} />
    }}
  • 1
  • 2
  • 3
  • 4

通过上面的方法来实现页面的跳转,同时将导航器作为属性进行传递过去。之前说过,route需要进行配置,通过initialRoute方法来对我们的路由进行初始化, 
如下所示:

    initialRoute={{ name: defaultName, component: defaultComponent }}
  • 1

initialRoute是一个对象,我们通过给对象设置名称和对应的组件完成route的初始化,即只要传入需要跳转的组件的名称和组建对象,即可在renderScene中完成页面的跳转。

再回头看renderScene方法,route参数就是我们通过initialRoute初始化的对象,我们通过route.component即可获得我们需要渲染(即跳转到)的对象,然后在return的时候返回这个对象完成页面的跳转。为了防止出现问题,我们加上route.component为空的判断,如果不为空,再进行渲染。

        renderScene={(route, navigator) => {
            let Component = route.component;
            if(route.component){
                return <Component {...route.params} navigator={navigator} />
            }
        }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

configureScene

该方法用来设置指定路由对象的配置信息,从而改变场景的动画或者手势。

    configureScene={(route) => {
      //跳转的动画
      return Navigator.SceneConfigs.VerticalDownSwipeJump;
    }}
  • 1
  • 2
  • 3
  • 4

例如通过如下的方法我们就可以对我们即将要跳转的界面设置跳转动画。 
Navigator.SceneConfigs为我们提供了大量的跳转动画,具体可以参考如下文件。

MyProject\node_modules\react-native\Libraries\CustomComponents\Navigator\NavigatorSceneConfigs.js

这样我们就完成了在程序默认页面到我们自定义页面之间的跳转过程。

完整代码如下所示:

'use strict';
import React, {
  AppRegistry,
  Component,
  StyleSheet,
  Text,
  Image,  
  TextInput,
  View,
  Navigator
} from 'react-native';


import FirstPageComponent from './app/src/FirstPageComponent';

export default class MyProject extends React.Component {
    render() {
        var defaultName = 'FirstPageComponent';
        var defaultComponent = FirstPageComponent;
        return (
        <Navigator
          //指定了默认的页面,也就是启动app之后会看到的第一屏,需要两个参数,name跟component
          initialRoute={{ name: defaultName, component: defaultComponent }}
          configureScene={(route) => {
            //跳转的动画
            return Navigator.SceneConfigs.FadeAndroid;
          }}
          renderScene={(route, navigator) => {
            let Component = route.component;
            if(route.component){
                return <Component  navigator={navigator} />
            }
          }} />
        );
    }
} 

AppRegistry.registerComponent('MyProject', () => MyProject);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

其中FirstPageComponent是我们自定义的一个组件,没有添加功能,只放了一个Text,如下所示:

import React,{
    View,
    Text,
} from 'react-native';

export default class FirstPageComponent extends React.Component{
    constructor(props){
        super(props);
        this.state = {};
    }

    render(){
        return (
            <View>
                <Text>我是默认页面</Text>
            </View>
            );
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

如果我们现在想要实现一个从FirstPageComponent到另一个页面之间的跳转,那我们需要怎么做呢?

因为我们之前在页面跳转的时候将导航器对象作为属性传递给了我们的FirstPageComponent,那么我们此时就可以获取这个navigator对象,navigator中有很多方法可以供我们调用进行导航。

首先我们给创建一个可点击的区域包裹Text,这样点击Text就可以触发事件,如下所示,改造render,

    render() {
        return (
            <View>
                <TouchableOpacity onPress={this._pressButton.bind(this)}>
                    <Text>点我跳转</Text>
                </TouchableOpacity>
            </View>
        );
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

我们先不关注TouchableOpacity是什么,只知道他是一片可点击的区域,并且拥有点击事件即可。

然后我们实现_pressButton方法,如下所示:

    _pressButtoon(){
        const { navigator} = this.props;
        if (navigator) {
            navigator.push({
                name:'SecondPageComonent',
                component:SecondPageComonent,
            })
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

我们从传递过来的属性中获取navigator,然后调用navigator的push方法,push方法接收的参数为route对象,我们定义route对象的名称和组件对象,将其放入路由栈,这样我们通过操控路由栈的方式实现了另一个页面的跳转。

这样我们改造后的FirstPageComponent如下所示:

import React,{
    View,
    Text,
    TouchableOpacity
} from 'react-native';

import SecondPageComonent from "./SecondPageComponent";

export default class FirstPageComponent extends React.Component{
    constructor(props){
        super(props);
        this.state = {};
    }

    _pressButtoon(){
        const { navigator} = this.props;
        if (navigator) {
            navigator.push({
                name:'SecondPageComonent',
                component:SecondPageComonent,
            })
        }
    }

    render(){
        return (
            <View>
                <TouchableOpacity onPress={this._pressButtoon.bind(this)}>
                    <Text>点我跳转</Text>
                </TouchableOpacity>
            </View>
            );
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

其中SecondPageComonent是我们定义的另一个组件,实现代码如下所示:

import React,{
    View,
    Text,
    TouchableOpacity,
} from 'react-native';

import FirstPageComponent from './FirstPageComponent';

export default class SecondPageComponent extends React.Component{
    constructor(props){
        super(props);
        this.state = {};
    }

    _pressButton(){
        const { navigator } = this.props;
        if(navigator){
            navigator.pop();
        }
    }

    render(){
        return (
            <View>
                <TouchableOpacity onPress={this._pressButton.bind(this)}>
                    <Text>点我跳转回去</Text>
                </TouchableOpacity>
            </View>
            );
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

在SecondPageComponent中,我们通过控制路由栈将页面出栈的方式pop()完成跳转回到第一个页面的功能。

我们发现,页面的跳转都是通过navigator对象的一系列方法通过对路由栈的操控来实现页面之间跳转加载的功能的,我们看一下导航器都有那些方法:

getCurrentRoutes() - 获取当前栈里的路由,也就是push进来,没有pop掉的那些。 
jumpBack() - 跳回之前的路由,当然前提是保留现在的,还可以再跳回来,会给你保留原样。 
jumpForward() - 上一个方法不是调到之前的路由了么,用这个跳回来就好了。 
jumpTo(route) - 跳转到已有的场景并且不卸载。 
push(route) - 跳转到新的场景,并且将场景入栈,你可以稍后跳转过去 
pop() - 跳转回去并且卸载掉当前场景 
replace(route) - 用一个新的路由替换掉当前场景 
replaceAtIndex(route, index) - 替换掉指定序列的路由场景 
replacePrevious(route) - 替换掉之前的场景 
immediatelyResetRouteStack(routeStack) - 用新的路由数组来重置路由栈 
popToRoute(route) - pop到路由指定的场景,其他的场景将会卸载。 
popToTop() - pop到栈中的第一个场景,卸载掉所有的其他场景。

参数的传递

当我们从一个页面跳转到另一个页面的时候,总免不了需要进行参数的传递,那么我们怎么将参数传递到另一个页面呢?

我们可以通过push()方法将参数传递过去。

首先我们需要明确FirstPageComponent,MyProject和SecondPageComponent三者之间的关系,程序启动时首先会启动MyProject,然后看到在MyProject中有一个导航器,该导航器初始化路由的时候获取了我们的FirstPageComponent,将其解析为一个组件在renderScene的时候将其加载到页面上。我们再来看一下导航器加载的方法:

        renderScene={(route, navigator) => {
            let Component = route.component;
            if(route.component){
                return <Component  navigator={navigator} />
            }
        }} 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

我们所有的组件都是通过导航器加载到页面上的,第一个页面是,第二个页面并不是由第一个页面启动的,而是有导航器控制路由栈来显示在页面上的,我们在renderScene是获取到第一个页面,并且将其渲染到屏幕上,我们在第一个页面中设置的push信息也是将信息传递给导航器的,那么我们就可以在这个时候将需要传递给Navigator,然后让其在传递给第二个页面,这样就可以完成参数的传递。

首先我们更改FirstPageComponent的按钮点击事件,如下所示:

        navigator.push({
            name:'SecondPageComonent',
            component:SecondPageComonent,
            params:{
                message:"I am from FirstPageComponent",
            }
        })
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

然后在Navigator中获取,如下所示:

        renderScene={(route, navigator) => {
            let Component = route.component;
            if(route.component){
                return <Component  {...route.params} navigator={navigator} />
            }
        }} 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在这里就相当于将参数传递给了Navigator,展开成然后我们就可以在第二个页面中通过props.message获取到信息,如下所示,添加页面挂载时的方法,设置状态的方法将获取到的参数保存在state中:

    componentDidMount(){
        this.setState({
            message:this.props.message,
        });
    }
  • 1
  • 2
  • 3
  • 4
  • 5

如果当我们返回的时候需要携带参数,我们可以通过给navigator设置一个回调方法,用于给第一个页面设置信息,这样就可以完成返回时数据的传递了。

完整代码如下所示:

index.android.js

'use strict';
import React, {
  AppRegistry,
  Component,
  StyleSheet,
  Text,
  Image,  
  TextInput,
  View,
  Navigator
} from 'react-native';


import FirstPageComponent from './app/src/FirstPageComponent';

export default class MyProject extends React.Component {
    render() {
        var defaultName = 'FirstPageComponent';
        var defaultComponent = FirstPageComponent;
        return (
        <Navigator
          //指定了默认的页面,也就是启动app之后会看到的第一屏,需要两个参数,name跟component
          initialRoute={{ name: defaultName, component: defaultComponent }}
          configureScene={(route) => {
            //跳转的动画
            return Navigator.SceneConfigs.FadeAndroid;
          }}
          renderScene={(route, navigator) => {
            let Component = route.component;
            if(route.component){
               return <Component {...route.params} navigator={navigator} />
            }
          }} />
        );
    }
} 

AppRegistry.registerComponent('MyProject', () => MyProject);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

FirstPageComponent.js

import React,{
    View,
    Text,
    TouchableOpacity
} from 'react-native';

import SecondPageComonent from "./SecondPageComponent";

export default class FirstPageComponent extends React.Component{
    constructor(props){
        super(props);
        this.state = {
            resultMessage:"hello",
        };
    }

    _pressButtoon(){
        var _this = this;
        const { navigator} = this.props;
        if (navigator) {
            navigator.push({
                name:'SecondPageComonent',
                component:SecondPageComonent,
                params:{
                    message:"I am from FirstPageComponent",
                    getResult:function(myMessage){
                        _this.setState({
                            resultMessage:myMessage,
                        })
                    }
                }
            })
        }
    }

    render(){
        return (
            <View>
                <TouchableOpacity onPress={this._pressButtoon.bind(this)}>
                    <Text>{this.state.resultMessage}</Text>
                </TouchableOpacity>
            </View>
            );
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

SecondPageComponent.js

import React,{
    View,
    Text,
    TouchableOpacity,
} from 'react-native';

import FirstPageComponent from './FirstPageComponent';

export default class SecondPageComponent extends React.Component{
    constructor(props){
        super(props);
        this.state = {
            message:"",
        };
    }

    componentDidMount(){
        this.setState({
            message:this.props.message,
        });
    }

    _pressButton(){
        const { navigator } = this.props;
        if(this.props.getResult){
            this.props.getResult("This is from SecondPageComponent");
        }

        if(navigator){
            navigator.pop();
        }
    }

    render(){
        return (
            <View>
                <TouchableOpacity onPress={this._pressButton.bind(this)}>
                    <Text>{this.state.message}</Text>
                </TouchableOpacity>
            </View>
            );
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

最终效果如下所示: 
ReactNative页面跳转Navigator

点赞
收藏
评论区
推荐文章
LinMeng LinMeng
2年前
Vue 重复进入相同路由警报
路由守卫重复进入两次,报错(虽然页面还可以运行)原因:vuerouter路由版本更新产生的问题,导致路由跳转失败抛出该错误,但并不影响程序功能Uncaught(inpromise)Error:Redirectedwhengoingfrom"/productDetail?VNK326acc75"to"/productTerms"via
LinMeng LinMeng
3年前
this.$router.replace和this.$router.push及this.$router.go()的区别
this.$router.push1.跳转到指定URL,向history栈添加一个新的记录,点击后退会返回至上一个页面2.声明式<routerlink:to"...."编程式router.push(...)//该方法的参数可以是一个字符串路径,或者一个描述地址的对象。this.$router.push('/index')
Easter79 Easter79
2年前
tp5 修改自带success或error跳转模板页面
tp5修改自带success或error跳转模板页面我们在使用tp5或者tp3.2的时候,用的成功或者失败跳转提示页面一般是用框架的。在后续开发过程中,根据实际项目需要,也是可以更改的,在此分享一个自用的模板。首先是看一下tp框架自带的跳转模板页面,以tp5为例在config.php中,我
Caomeinico Caomeinico
2年前
小程序手动实现路由拦截
小程序中并没有像vuerouter一样的路由拦截功能,所以需要自己手动实现,下面就把具体的实现方法分享出来供大家参考。具体实现思路与vue相同,定义一个全局的token变量,进入某一个页面的时候判断是否存在这个token是否存在,存在则正常跳转,不存在则跳转到登录页面。创建一个工具文件夹,创建一个routers.js,封装路由拦截的具体代码如
Joyce464 Joyce464
3年前
RN react-navigation使用
一、命令安装npminstallreactnavigationsave该库包含三类组件:(1)StackNavigator:用来跳转页面和传递参数(2)TabNavigator:类似底部导航栏,用来在同一屏切换不同页面
马丁路德 马丁路德
3年前
微信小程序 - 路由实践
欢迎来到我博客阅读:1\.前言在微信小程序由一个App()实例,和众多Page()组成。而在小程序中所有页面的路由全部由框架进行管理,框架以栈的形式维护了所有页面,然后提供了以下API来进行路由之间的跳转:1.wx.navigateTo2.wx.redirectTo3.wx.navigateBack4.
浩浩 浩浩
3年前
【Flutter实战】 路由管理
2.2路由管理路由(Route)在移动开发中通常指页面(Page),这跟web开发中单页应用的Route概念意义是相同的,Route在Android中通常指一个Activity,在iOS中指一个ViewController。所谓路由管理,就是管理页面之间如何跳转,通常也可被称为导航管理。Flutter中的路由管理和原生开发类似,无论是Android还是
Easter79 Easter79
2年前
springMVC实现登陆
页面打开跳转到登陆页面登陆成功跳转到成功页面登陆失败再次返回登录页面,并增加提示信息1、首页跳转到登陆页面  Tomcat服务器启动时默认加载WEBINF下的index.jsp,可以通过修改xml配置的方式来改变Tomcat这一默认行为。这里使用springMVC来实现这个功能。  第一种实现
Wesley13 Wesley13
2年前
3. Vue
路由是根据不同的url地址展现不同的内容或页面。前端路由就是把不同路由对应不同的内容或页面的任务交给前端来做(在单页面应用,大部分页面结构不变,只改变部分内容的使用),之前是通过服务器根据url的不同返回不同的页面。前端路由优点:用户体验好,不需要每次都从服务器全部获取,快速展现给用户缺点:不利于SEO,使用浏
Wesley13 Wesley13
2年前
10分钟彻底搞懂单页面应用路由
上一次,跟大家科普了小程序的自定义路由routes,开启了路由之旅;今天,顺势就单页面应用路由,跟大家唠个五毛钱,如果唠得不好……退…一块钱?单页面应用特征假设:在一个web页面中,有1个按钮,点击可跳转到站内其他页面。多页面应用:点击按钮,会从新加载一个html资源,刷新整个页面;单页面应