react-navigation页面跳转也是根据路由来执行的,很意外的和ARouter的实现极其类似,只要在一个集中式的路由注册控制中进行相应的声明就可以做到,很简单。
react-navigation 是目前RN官方建议使用的导航组件,它分为三种导航方式:栈式导航、标签导航和抽屉式导航。其中栈式导航和标签导航可以嵌套调用
栈式导航——StackNavigator
栈式导航就好像将一个个界面放入在一个栈中一样。只有在栈顶的界面对用户是可见的。它可以轻松的实现出Android的活动栈的效果。
StackNavigation的创建
StackNavigation接口的定义为: createStackNavigator(RouterConfigs, StackNavigatorConfig);
RouteConfigs用来配置RN应用的路由信息。它的结构是:
{
//路由名称: 路由配置
Home: {
screen: Home, // 对应于RN组件的名称,必须有
path:'path1/path2', // 可选项,使用url导航时用到, 如 web app 和 Deep Linking
navigationOptions: {} //此处设置会覆盖组件内的static navigationOptions设置
}
}
而StackNavigatorConfig表示的是路由的参数,在StackNavigatorConfig的几个重点字段如下所示:
{
initialRouterName: '' // 默认显示界面,需要是上面RouteConfigs中定义的界面
// 该字段不定义时,进入Navigator的显示界面是RouteConfigs中的第一个界面
defaultNavigationOptions: ({navigations}) => { }
// 屏幕导航的默认显示,包括左右两边显示的图案或文字,标题等
//也可以在组件内用static navigationOptions设置,在组件内的设置会覆盖此处设置
……
}
同时,在navigator函数跳转界面携带navigation属性时,开发者还可以携带通用的界面属性,如下所示:
export default class Demo extends Component {
render () {
return (
<Navi screenProps={ key:value } />
);
}
}
开发者可以在各个界面中都可以通过 this.props.screenProps.key 来获取相应的属性值。
描述完这些,我们就可以对StackNavigation的创建有一个整体性的认识,如下面的代码段所示:
import { createStackNavigator } from 'react-navigation-stack';
import HomeOne from './HomeOne';
import HomeTwo from './HomeTwo';
// 注册导航
const Navs = createStackNavigator({
HomeOne: { screen: HomeOne },
HomeTwo: {
screen: HomeTwo, // 必须, 其他都是非必须
path: 'app/homeTwo',
navigationOptions: {}
},
}, {
initialRouteName: 'Home',
//如果在StackNavigatorConfig里面配置了navigationOptions,这些参数会作用与RouteConfigs里面的所有路由的子页面,如果路由子页面里面设置了static navigationOptions那么会覆盖此处配置的全局参数
navigationOptions: {
headerTitle: "首页",
headerBackTitle: null,
headerTintColor: "#333",
cardStack: {
gesturesEnabled: true//是否允许右滑返回,在iOS上默认为true,在Android上默认为false
}
},
mode: 'card', // 页面切换模式, 左右是card(相当于iOS中的push效果), 上下是modal(相当于iOS中的modal效果)
headerMode: 'screen',
// 导航栏的显示模式, screen: 随屏幕滑动消失重现(Android风格), float: 永远存在, none: 隐藏导航栏
onTransitionStart: () => { }, // 页面切换开始时的回调函数
onTransitionEnd: () => { } // 页面切换结束时的回调函数
});
export default class Demo extends Component {
render () {
return (
<Navi />
);
}
}
navigation参数的使用
当一个RN组件通过StackNavigator接口加载时,它会自动得到一个名为navigation的属性。这个属性是一个对象,对象的成员函数可以让开发者操纵路由。
这个属性下面有一个state的变量记录了当前组件的路径参数,如下图所示:
{
routeName: 'XXXX', // 路径名称
key: 'XXXX', // 路径的key值,系统自动生成,用于唯一的标识一个路由
params: {} // 路径携带的参数
}
同时,自动得到的navigation属性中有些公开的参数,它们可以用来操控导航:
-
navigate(routeName,params) 跳转动作,完成在导航栏内部的跳转
-
setParams({key:value}) 修改导航栏带的参数值,同时也可以给组件的导航栏设置自己特定的参数值
//TODO: 这里有一个问题,即如果在一个组件中setParams更改了参数,回到父界面这个Params会保存吗?
-
goBack(key) 返回函数,key值是可选项。
在APP的开发中,开发者经常发现自己需要关闭多个组件,假设有ABC三个成栈式的组件,我们要从C直接到A,为了实现这个功能,我们就要同步B拿到A的key值,然后再将这个key传到C组件中,开发者调用带有A组件key值的goBack函数,就表示希望从C返回到A
同时,在项目中,没有导入BackHandler组件对Android平台的返回键按下事件的捕捉和处理。react-navigation组件将自动帮助开发者完成这个任务。
-
getParam(paramName, defaultValue) 得到navigation.state.params 中的某些字段值,这里注意,得到的不是navigation中的字段值
同时,对于不同的界面,我们会想要定制不同的导航栏,这时就可以定义一个静态成员变量navigationOptions,来覆盖传递进来的navigation属性。它的设置方式如下所示:
static navigationOptions = ({navigation}) => {
title:
……
}
标签导航——TabNavigator
标签导航也是RN中很常见的一种导航方式,它的效果类似于一个Activity上多个Fragment的显示和销毁
TabNavigator接口
接口的类型和StackNavagator完全一致,这不过多赘述,只不过因为StackNavigatorConfig变成了TabNavigatorConfig,所以参数有很大的变化,字段变化如下所示:
{
tabBarPosition: 'top'/'bottom' // 标签栏在屏幕上方显示的位置
swipeEnabled: true/false // 是否允许通过手势滑动来切换标签
animationEnabled: true/false // 切换标签时动画的显示
lazy: true/false // 懒加载,只渲染需要显示的标签界面
// 意思是在app打开的时候将底部标签栏全部加载,默认false,为true时初始显示性能提高
order: {} // 存放标签名称的数组,用于标识组件显示的顺序,如果不设置按RouteConfig中的顺序显示
tabBarOptions: {
showIcon: true/false
// 在Android中,默认不显示导航栏的图标,即使在tabBarOptions中定义了图标
// 需要将showIcon设置为true才能显示
}
initialRouterName:
backBehavior: // 默认情况下点击back键将返回到initialRouteName的标签页
// 因为TabNavigator的界面是平行的界面,所以设置none让它退出标签导航
}
对于标签导航的每一个组件,都有下面结构的navgationOptions:
{
title:
tabBarVisible:
tabBarIcon:
tabBarLabel:
}
栈式导航和标签导航的嵌套使用
在creatStackNavigator和createTabNavigator的RouteConfig中如下设置即可:
const RNNavigator = createStackNavigator({
TabNavigator: { screen: TabNavigator },
……
}
抽屉导航——DrawerNavigator
//TODO:目前还没有使用过,等待后续补充
参考文档
[1] RN react-navigation使用: https://blog.csdn.net/gongch0604/article/details/79957358
[2] React Native 跨平台移动应用开发(第二版)