前言

  不久前自己也完整开发了一个React-Native项目,对其中的一些知识存在疑惑,再加上项目时间比较紧张,来不及做系统的学习。现在来回顾自己开发当中存在的疑惑点,和大家分享。第一篇是关于路由框架react-navigation,当时其实也没有好好看文档,现在回头看路由设计的确实比较乱,如果没看过文档建议直接去看文档,而后再看此篇文章。主要介绍createStackNavigator,createSwitchNavigator,createBottomTabNavigator,createMaterialTopTabNavigator,这四类路由框架,以及他们的组合使用。

createStackNavigator

  顾名思义,其实这就是一种基于栈的路由管理方式,栈的特点就是先入后出,最新入栈的界面会显示在最顶部,这也是Android管理Activity的方式,也是React-Native App打开页面最主要的方式。

  

  export function createStackNavigator(
routeConfigMap: NavigationRouteConfigMap,
stackConfig?: StackNavigatorConfig
): NavigationContainer;

该方法提供两个参数,一个是NavigationRouteConfigMap,当中存储的一些你声明的组件,他们之间构成了一个单独的路由。还有一个参数是StackNavigatorConfig,它允许你对路由做一个全局的设置,比如说是否显示头部,头部的主题等等。这边建议都不显示头部,更多的时候,页面的头部不尽相同,通过自定的这种形式会对开发更加的友好。需要注意的是,在最新版本的react-navigation当中,必须通过createAppContainer包裹导出。通过创建js文件:AppNavigator.js,一个完整的基于createStackNavigator的例子如下:

import {
createStackNavigator,
createSwitchNavigator,
createAppContainer,
createBottomTabNavigator,
createMaterialTopTabNavigator
} from 'react-navigation'
import SplashPage from "../page/Splash/SplashPage";
import HomePage from "../page/Home/HomePage";
import Feather from "react-native-vector-icons/Feather"
import Page1 from "../page/bottom/Page1";
import Page2 from "../page/bottom/Page2";
import Page3 from "../page/bottom/Page3";
import React from "react";
import Top1 from "../page/top/Top1";
import Top2 from "../page/top/Top2";
import Top3 from "../page/top/Top3"; const InitNavigator = createStackNavigator({
SplashPage: {
screen: SplashPage,
navigationOptions: {
header: null
}
},
Page1: {
screen: Page1,
navigationOptions: {
header: null
}
},
Page2: {
screen: Page2,
navigationOptions: {
header: null
}
},
Page3: {
screen: Page3,
navigationOptions: {
header: null
}
}, },{ }); export default createAppContainer(InitNavigator);

这个时候我们只需要修改App.js,就可以完成接入路由这个操作了。

import React, {Component} from 'react';
import {Platform, StyleSheet, Text, View, TouchableOpacity} from 'react-native';
import AppNavigator from "./app/navigation/AppNavigator"; type Props = {};
export default class App extends Component<Props> {
render() {
return (
<AppNavigator/>
);
}
}

可以看到,单个js文件中的路由以单个组件的形式提供,可以预见,在项目路由复杂,项目路由多这种情况下react-navigation也一样可以轻松的管理路由。具体的页面代码就不再展示,效果如下:

createSwitchNavigator

switch,意思也比较明显,就是选择的意思。也就是说,当你使用这个路由时,内存中只会存在一个页面或者一个路由(多路由情况)。其实,大多数App都有一个欢迎界面,这个界面在App中只会显示一次,如果单单是使用栈的形式,不好控制出栈的操作,实现起来就比较复杂,那么我们的createSwitchNavigator就能派上用场了。当跳转到我们的主路由的时候,欢迎界面也就消失了。来看一下createSwitchNavigator中提供的参数:

  export function createSwitchNavigator(
routeConfigMap: NavigationRouteConfigMap,
switchConfig?: SwitchNavigatorConfig
): NavigationContainer;

可以看到和createStackNavigator大同小意,也是一个路由管理集合,和一个可以对界面的总体设置,那么要实现我们上面想要的效果如何去做呢?其实也非常简单,代码如下:

import {
createStackNavigator,
createSwitchNavigator,
createAppContainer,
createBottomTabNavigator,
createMaterialTopTabNavigator
} from 'react-navigation'
import SplashPage from "../page/Splash/SplashPage";
import HomePage from "../page/Home/HomePage";
import Feather from "react-native-vector-icons/Feather"
import Page1 from "../page/bottom/Page1";
import Page2 from "../page/bottom/Page2";
import Page3 from "../page/bottom/Page3";
import React from "react";
import Top1 from "../page/top/Top1";
import Top2 from "../page/top/Top2";
import Top3 from "../page/top/Top3"; const InitNavigator = createStackNavigator({
Page1: {
screen: Page1,
navigationOptions: {
header: null
}
},
Page2: {
screen: Page2,
navigationOptions: {
header: null
}
},
Page3: {
screen: Page3,
navigationOptions: {
header: null
}
}, },{ }); const AppRoot = createSwitchNavigator({
SplashPage: {
screen: SplashPage,
navigationOptions: {
header: null
}
},
Main: InitNavigator,
});
export default createAppContainer(AppRoot);

那么这个时候,我们的splash界面就不再是跳转到page1了。而是在AppRoot中的Main了

import BasePage from "../../base/BasePage";
import {Platform, StyleSheet, Text, View, TouchableOpacity} from 'react-native';
import React, {Component} from 'react'; export default class SplashPage extends BasePage { render() {
return (
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<TouchableOpacity onPress={() => {
this.goNextPage("Main")
}}>
<Text>Splash</Text>
</TouchableOpacity>
</View>
);
}
}

现在来看下效果

createBottomTabNavigator

如果我们要实现类似微信首页多tab多界面的时候,createBottomTabNavigator就能派上用场了,他通过单个路由管理多个tab,我们来看一下实现的参数:

 export function createBottomTabNavigator(
routeConfigMap: NavigationRouteConfigMap,
drawConfig?: BottomTabNavigatorConfig
): NavigationContainer;

哎呀,和前面两个一样,也是一个路由管理集合,和一个可以对界面的总体设置。具体设置属性的参数这里不多说,以后的文章会说到,我们把上面提到的两个路由结合起来,实现一个大部分App都有的一个正常路由流程。外部是个createSwitchNavigator做splash和主路由,主路由通过createStackNavigator用栈管理,但是第一个page我们使用createBottomTabNavigator做首页。那么代码如下:

import {
createStackNavigator,
createSwitchNavigator,
createAppContainer,
createBottomTabNavigator,
createMaterialTopTabNavigator
} from 'react-navigation'
import SplashPage from "../page/Splash/SplashPage";
import HomePage from "../page/Home/HomePage";
import Feather from "react-native-vector-icons/Feather"
import Page1 from "../page/bottom/Page1";
import Page2 from "../page/bottom/Page2";
import Page3 from "../page/bottom/Page3";
import React from "react";
import Top1 from "../page/top/Top1";
import Top2 from "../page/top/Top2";
import Top3 from "../page/top/Top3"; let hotSelest = <Feather
name={'activity'}
size={26}
color='red'
/>;
let hotUnSelest = <Feather
name={'activity'}
size={26}
/>;
let pointSelect = <Feather
name={'thumbs-up'}
size={26}
color='red'
/>;
let pointUnSelect = <Feather
name={'thumbs-up'}
size={26}
/>;
let mineSelect = <Feather
name={'user'}
size={26}
color='red'
/>;
let mineUnSelect = <Feather
name={'user'}
size={26}
/>; const BottomNavigator = createBottomTabNavigator({
Page1: {
screen: Page1,
navigationOptions: {
tabBarLabel: '最热',
tabBarIcon: ({tinColor, focused}) => (focused ? hotSelest : hotUnSelest)
}
},
Page2: {
screen: Page2,
navigationOptions: {
tabBarLabel: '点赞',
tabBarIcon: ({tinColor, focused}) => (focused ? pointSelect : pointUnSelect)
}
},
Page3: {
screen: Page3,
navigationOptions: {
tabBarLabel: '我的',
tabBarIcon: ({tinColor, focused}) => (focused ? mineSelect : mineUnSelect)
}
},
}, {
tabBarOptions: {
activeTintColor: '#e91e63',
header: null,
}
}); const InitNavigator = createStackNavigator({
Page1: {
screen: BottomNavigator,
navigationOptions: {
header: null
}
},
Top1: {
screen: Top1,
navigationOptions: {
header: null
}
},
Top2: {
screen: Top2,
navigationOptions: {
header: null
}
}, },{ }); const AppRoot = createSwitchNavigator({
SplashPage: {
screen: SplashPage,
navigationOptions: {
header: null
}
},
Main: InitNavigator,
});
export default createAppContainer(AppRoot);

通过设置lable,icon两个属性,设置图片和文字,这边没有图片,所以使用了一个三方库,有兴趣的可以了解一下。你也可以在,全局的设置当中设置是否显示lable和icon和文字选中颜色等等。首页的第一个界面点击之后会跳转到top界面,效果如下:

createMaterialTopTabNavigator

同过实现一个material风格的顶部选择导航,相对于createBottomTabNavigator,有些属性不同。我们来看看实现方法:

export function createMaterialTopTabNavigator(
routeConfigMap: NavigationRouteConfigMap,
drawConfig?: TabNavigatorConfig
): NavigationContainer;

也是大同小异,具体的属性差别实践之后体会更加深刻,我也会在后面介绍,包括一下高级的用法。我们让首页第一个变成materialtop的风格,代码也是非常简单,我们在上面的基础上修改一下:

import {
createStackNavigator,
createSwitchNavigator,
createAppContainer,
createBottomTabNavigator,
createMaterialTopTabNavigator
} from 'react-navigation'
import SplashPage from "../page/Splash/SplashPage";
import HomePage from "../page/Home/HomePage";
import Feather from "react-native-vector-icons/Feather"
import Page1 from "../page/bottom/Page1";
import Page2 from "../page/bottom/Page2";
import Page3 from "../page/bottom/Page3";
import React from "react";
import Top1 from "../page/top/Top1";
import Top2 from "../page/top/Top2";
import Top3 from "../page/top/Top3"; const TopNavigator= createMaterialTopTabNavigator({
TopOne:{
screen:Top1
},
TopTwo:{
screen:Top2
},
TopThree:{
screen:Top3
},
}); let hotSelest = <Feather
name={'activity'}
size={26}
color='red'
/>;
let hotUnSelest = <Feather
name={'activity'}
size={26}
/>;
let pointSelect = <Feather
name={'thumbs-up'}
size={26}
color='red'
/>;
let pointUnSelect = <Feather
name={'thumbs-up'}
size={26}
/>;
let mineSelect = <Feather
name={'user'}
size={26}
color='red'
/>;
let mineUnSelect = <Feather
name={'user'}
size={26}
/>; const BottomNavigator = createBottomTabNavigator({
Page1: {
screen: TopNavigator,
navigationOptions: {
tabBarLabel: '最热',
tabBarIcon: ({tinColor, focused}) => (focused ? hotSelest : hotUnSelest)
}
},
Page2: {
screen: Page2,
navigationOptions: {
tabBarLabel: '点赞',
tabBarIcon: ({tinColor, focused}) => (focused ? pointSelect : pointUnSelect)
}
},
Page3: {
screen: Page3,
navigationOptions: {
tabBarLabel: '我的',
tabBarIcon: ({tinColor, focused}) => (focused ? mineSelect : mineUnSelect)
}
},
}, {
tabBarOptions: {
activeTintColor: '#e91e63',
header: null,
}
}); const InitNavigator = createStackNavigator({
Page1: {
screen: BottomNavigator,
navigationOptions: {
header: null
}
},
Top1: {
screen: Top1,
navigationOptions: {
header: null
}
},
Top2: {
screen: Top2,
navigationOptions: {
header: null
}
}, },{ });
const AppRoot = createSwitchNavigator({
SplashPage: {
screen: SplashPage,
navigationOptions: {
header: null
}
},
Main: InitNavigator,
});
export default createAppContainer(AppRoot);

在createBottomTabNavigator的第一个界面,加入了materialtop的路由,来看看效果:

总结

 来做一个简单的总结:

1.这几种路由无非就是两个参数,一个是界面的集合以及全局界面属性的设置,不同的路由属性不同,你也可以在单个界面设置他的属性。

2.路由的使用需要通过createAppContainer包裹,他以一个组件的形式体现在我们的界面上,这也是新版本加上的,无疑让他更加的灵活。

3.一个完整的App路由绝对不是单个路由那么简单的,要好好思考App的业务逻辑,设置出专属于你的路由,react-navigation完全能胜任这个工作。

最后,核心代码都在上面,我就不贴项目连接了。

一起来学习React-Native之react-navigation基本解析的更多相关文章

  1. 【React Native】React Native项目设计与知识点分享

    闲暇之余,写了一个React Native的demo,可以作为大家的入门学习参考. GitHub:https://github.com/xujianfu/ElmApp.git GitHub:https ...

  2. React Native之React速学教程(下)

    概述 本篇为<React Native之React速学教程>的最后一篇.本篇将带着大家一起认识ES6,学习在开发中常用的一些ES6的新特性,以及ES6与ES5的区别,解决大家在学习Reac ...

  3. React Native之React速学教程(中)

    概述 本篇为<React Native之React速学教程>的第一篇.本篇将从React的特点.如何使用React.JSX语法.组件(Component)以及组件的属性,状态等方面进行讲解 ...

  4. React Native之React速学教程(上)

    概述 本篇为<React Native之React速学教程>的第一篇.本篇将从React的特点.如何使用React.JSX语法.组件(Component)以及组件的属性,状态等方面进行讲解 ...

  5. React Native & react-native-web-player & React Native for Web

    React Native & react-native-web-player & React Native for Web https://github.com/dabbott/rea ...

  6. React Native之React Navigation踩坑

    自动重装系统之后,已经很长一段时间没有来写React Native了,今天空闲之余,决定重新配置React Native的开发环境,继续踩坑... React Native的开发环境配置狠简单,只要依 ...

  7. 小谈React、React Native、React Web

    React有三个东西,React JS 前端Web框架,React Native 移动终端Hybrid框架,React Web是一个源码转换工具(React Native 转 Web,并之所以特别提出 ...

  8. [React Native]升级React Native版本

    React Native正式版本还没发布,但是小版本基本上每个月都更新1-2次.9月11号又更新了0.33版本,其中有两个增强功能正好是项目中用到的. 添加Android6.0权限验证API Add ...

  9. react native 集成react navigation报错

    集成后出现:“Invalid escape sequence at line 1 column 29 path $[0].name”的错误. 解决办法:

  10. [React Native + Firebase] React Native: Real time database with Firebase -- setup & CRUD

    Install: npm i --save firebase // v3.2.1 Config Firebase: First we need to require Firebase: import ...

随机推荐

  1. linux命令管道符

    linux多命令 ; 多个命令互相不影响 a && b  a命令执行成功才执行b命令 a || b a成功不执行b  a失败执行b ifconfig && echo & ...

  2. redis过期事件回调函数,与有序集合

    https://cloud.tencent.com/developer/article/1347437  python中的Redis键空间通知(过期回调) set notify-keyspace-ev ...

  3. 解决 React-Native: Android project not found. Maybe run react-native android first?

    在终端运行命令react-native run-android时报错Android project not found. Maybe run react-native android first? 解 ...

  4. Android笔记(二十九) Android中的异步更新(一) Android中的线程

    Java中的线程 1. 线程的两种实现方式 ①继承Thread类 ②实现Runnable接口 两者区别在于,Thread这个类的对象,代表的是一个线程,而Runnable的对象,代表的是线程体(也就是 ...

  5. Android小经验:启动Eclipse,出现提示“......发现了以元素'd:skin'开头的无效内容。此处不应含有子元素...”

    如图所示: 解决办法: 进入sdk目录下,把D:\android-sdks\system-images\android-22\android-wear\armeabi-v7a\devices.xml和 ...

  6. redis3.2 aof重写

    redis关闭aof,缩容,redis实例一直在重写. 原因也是redis3.2的bug,aof重写是没有判断aof是否开启. redis缩容后改变的是redis重写的min_size,缩容之前,实例 ...

  7. Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)-E. Let Them Slide-思维+数据结构

    Manthan, Codefest 19 (open for everyone, rated, Div. 1 + Div. 2)-E. Let Them Slide-思维+数据结构 [Problem ...

  8. Vue中的DOM操作

    1.在要获取的标签中添加 ref="xx" 示例: <button ref="btn">一个按钮</button> 2.在 mounte ...

  9. python函数名的应用、闭包和迭代器

    一.函数名的应用(第一类对象) 函数名是一个变量,但它是一个特殊的变量,与括号配合可以执行函数变量. 1.函数名的内存地址 def func(): print("哈哈") prin ...

  10. 模拟webpack 实现自己的打包工具

    本框架模拟webpack打包工具 详细代码个步骤请看git地址:https://github.com/jiangzhenfei/easy-webpack 创建package.json { " ...