ReactNative从零到完整项目-如何使用导航器跳转页面

2,509 阅读6分钟

项目连接: 93Laer/MyDemo ReactNative使用手册

关键词:
  • 场景(Scene):可简单的理解为一个界面中所有的组件构成了这个界面,其实就是构成了一个场景(Scene)
  • Navigator:官方推荐的一个纯JavaScript实现了一个导航栈,因此可以跨平台工作,同时也便于定制的一个导航器。 Scene官方实例:
import React, { Component } from 'react';
import { View, Text } from 'react-native';

export default class MyScene extends Component {
  static defaultProps = {
    title: 'MyScene'
  };

  render() {
    return (
      <View>
        <Text>Hi! My name is {this.props.title}.</Text>
      </View>
    )
  }
}

这就构成了一个scene,感觉相当于没解释,但是为了再一次练习props,在项目中我还是再写了一次

使用Navigator: 这里就不写了,按照官方的实例跑一次发现报错,报在'react-native'modules中找不到Navigator这个组件了,也提示了处理方法,但是我再看看官方文档发现其实现在官方推荐的事是Navigator的教程,所以接下来直接进入react-navigation库学习

image.png

react-navigation库使用:

安装module:npm install --save react-navigation 最简单使用(直接使用StackNavigator加载界面)

/**
 * 创建人:赖天兵
 * 时间: 2018/2/24
 * 简书:https://www.jianshu.com/u/2229fd214880
 * 掘金:https://juejin.cn/user/4107431170278478
 * github:https://github.com/93Laer
 * 描述:
 */
import { View, Text } from 'react-native';
import { StackNavigator } from 'react-navigation';
import React from 'react';
class NavigatorTest extends React.Component {
    render() {
        return (
            <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
                <Text>Home Screen</Text>
            </View>
        )
    }
}

export default StackNavigator({
    AppHome: {screen: NavigatorTest}
});

注意:

  • 1、 路由名称的大小写无关紧要,您可以使用小写字母home或大写字母Home,这取决于您。我们更喜欢大写我们的路线名称。
  • 2、screen组件唯一需要的配置是组件。您可以阅读关于StackNavigator参考中可用的其他选项的更多信息。
  • 3、在React Native中,从其中导出的组件App.js是您的应用程序的入口点(或根组件) - 它是每个其他组件从中下降的组件。在你的应用的根目录下对组件进行更多的控制通常比导出一个更有用StackNavigator,所以让我们导出一个只呈现我们的组件StackNavigator(其实简单讲就是在APP入口的时候就使用StackNavigator组件)。

效果图

在StackNavigator中添加多条线路(注册多个组件): 也很简单,就直接上代码解释重点了

/**
 * 创建人:赖天兵
 * 时间: 2018/2/24
 * 简书:https://www.jianshu.com/u/2229fd214880
 * 掘金:https://juejin.cn/user/4107431170278478
 * github:https://github.com/93Laer
 * 描述:
 */
import React from 'react';
import { View, Text } from 'react-native';
import { StackNavigator } from 'react-navigation';
class HomeScreen  extends React.Component {
    render() {
        return (
            <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
                <Text>Home Screen</Text>
            </View>
        )
    }
}
class DetailsScreen  extends React.Component {
    render() {
        return (
            <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
                <Text>Details Screen</Text>
            </View>
        );
    }
}
export default StackNavigator({
        //todo 1、直接展示
        //AppHome: {screen: HomeScreen}


        //todo 2、初始化多条线路,通过initialRouteName控制初始化那一个路由
        Home: {
            screen: HomeScreen,
        },
        Details: {
            screen: DetailsScreen,
        },
    },
    {
        //通过initialRouteName来控制初始化哪一个路由
        initialRouteName: 'Home',
    }
);

解释: 其实就是在堆栈中多初始化了几条线路,然后通过initialRouteName来控制来展示那一条。

实现跳转

问题一: 我们怎么从主路线(HomeScreen)移动到细节(DetailsScreen)路线?

接下来我们将HomeScreen修改一下,实现点击按钮跳转详情页的功能,代码如下:
class HomeScreen  extends React.Component {
    render() {
        return (
            <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
                <Text>Home Screen</Text>
                <Button
                    title="Go to Details"
                    //这里跳转的页面是我们已经在StackNavigator中注册了的,如果是没注册又会发生什么呢
                    onPress={() => this.props.navigation.navigate('Details')}
                    />
            </View>
        )
    }
}

效果

问题二: 当我们跳转一个我们未在StackNavigator中注册的界面又会发生什么呢? 我们直接将跳转代码改成onPress={() => this.props.navigation.navigate('XXX')},看看会怎样,结果就不展示了,其实就是没有任何效果,所以我们跳转的界面必须是在StackNavigator中注册了的。

官方原话: 如果我们this.props.navigation.navigate使用我们尚未定义的路由名称进行呼叫,则不会StackNavigator发生任何事情。换句话说,我们只能导航到已定义的路线StackNavigator- 我们无法导航到任意组件。

问题三: 那我们多次跳转同一个注册的界面,又会出现什么呢?

  • 首先我们将代码改成
class HomeScreen  extends React.Component {
    render() {
        return (
.
.
.
                    //这里跳转的页面是我们已经在StackNavigator中注册了的,如果是没注册又会发生什么呢
                    onPress={() => this.props.navigation.navigate('Details')}
                    />
.
.
}
class DetailsScreen  extends React.Component {
    render() {
.
.
.
                    //这里跳转的页面是我们已经在StackNavigator中注册了的,如果是没注册又会发生什么呢
                    onPress={() => this.props.navigation.navigate('Details')}
                    />
.
.
}
  • 效果
    多次跳转.gif

总结: 多次打开DetailsScreen页面,会创建新的DetailsScreen页面添加到堆栈

官方解释: 每次按“转到详细信息......再次”按钮时,它都会将新的屏幕推到顶部。这是我们原来的比较document.location.href分崩离析的地方,因为在网络浏览器中,这些不会被视为不同的路线,也不会将新条目添加到浏览器历史记录中 - navigate因为StackNavigator其行为更像网络window.history.pushState:每次调用时navigate都会推送一个新的路由到导航堆栈。

问题四: 我们怎样用代码控制回到上一个页面呢?其实这个就很简单了

  • 首先我们在DetailsScreen中添加代码
class DetailsScreen  extends React.Component {
    render() {
        return (
            <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
                <Text>Details Screen</Text>
                <Button
                    title="Go to Details again"
                    //这里跳转的页面是我们已经在StackNavigator中注册了的,如果是没注册又会发生什么呢
                    onPress={() => this.props.navigation.navigate('Details')}
                    />
                <Button
                    title="Go back"
                    onPress={() => this.props.navigation.goBack()}
                    />
            </View>
        );
    }
}

效果就不展示了,和点击返回按钮一样。

经过问题三和问题四,你肯定会想到,那如果我们有业务的逻辑是常见的要求是能够返回多个屏幕 - 例如,如果您在堆栈中有几个屏幕深度,并且想要将它们全部撤回到第一个屏幕。官方说我们将在“建立一个签名流”中讨论如何做到这一点 不过暂时我还没有找到解决办法,知道请留言

StackNavigator和Navigator相比有什么好处呢:
  • 1、新的导航库无论从性能还是易用性上都要大大好于老的Navigator!这是官方原话
  • 2、StackNavigator写起来更简单方便,读者 可以点击Navigator自己对比,尤其这点使用过Navigator和StackNavigator的人体会明显
  • 3、StackNavigator只能跳转已注册的界面,类似与安卓只能跳转在清单文件中注册的activity一样,而Navigator没有这个规则,但是必须将Navigator自身作为一个属性相互传递,而StackNavigator至少不需要我们手动传递(作为一个安卓开发来说,我更倾向StackNavigator)

喜欢请点赞,或是关注,后续将完善发布更多的文章,你的鼓励就是我的动力(程序员最大的动力莫过于同行的鼓励)