使用react native进行开发,不可避免的会使用到跳转。鉴于目前react native版本问题。一般使用react-navigation实现跳转。这也是官方推荐使用的组件。
createStackNavigator 为您的应用提供一种在屏幕之间转换的方式,其中每个新屏幕都放置在堆栈顶部。这个是我们实现跳转所要使用到的API。它的用法
createStackNavigator(RouteConfigs, StackNavigatorConfig);
RouteConfigs参数,我们用来写路由相关的配置。一般我们写具有跳转关系的View配置。比如,有A、B、C三个页面,我需要A、B、C三个页面同时具有跳转关系。即我可以从A跳转至B,亦可以从A跳转至C,B跳转至C等同级跳转。我们将A、B、C注册到RouteConfigs参数,同时,我们可以对这些页面进行一些样式操作。默认页面会有标题栏,返回按钮等样式。如果不需要,我们可以将其去除等操作。总而言之,我们可以用来注册我们期望具有跳抓功能的View页面
StackNavigatorConfig参数,用来设置一些跳转的默认操作,比如堆栈的默认屏幕视图,初始路线的参数等设置,按照需求进行设置,不过多做讲解。
const HomeStack = createStackNavigator({//设置HomeScreen页面与SettingView页面的跳转注册
HomeScreen: {
screen: HomeScreen,//注册View页面名称
navigationOptions: () => ({
header: null, //去除标题栏
headerBackTitle: null, //去除返回按钮
gesturesEnabled: true //是否可以使用手势来关闭此屏幕。在iOS上默认为true,在Android上默认为false
})
},
SettingView: {//注册设置页面
screen: SettingView,
navigationOptions: () => ({
header: null, //去除标题栏
headerBackTitle: null, //去除返回按钮
gesturesEnabled: true //是否可以使用手势来关闭此屏幕。在iOS上默认为true,在Android上默认为false
})
},
MapScreen: {//注册地图页面
screen: MapScreen,
navigationOptions: () => ({
header: null, //去除标题栏
headerBackTitle: null, //去除返回按钮
gesturesEnabled: true //是否可以使用手势来关闭此屏幕。在iOS上默认为true,在Android上默认为false
})
},
DetailInfo: {//注册业务详情页面
screen: DetailInfo,
navigationOptions: () => ({
header: null, //去除标题栏
headerBackTitle: null, //去除返回按钮
gesturesEnabled: true //是否可以使用手势来关闭此屏幕。在iOS上默认为true,在Android上默认为false
})
},
Appointment: {//注册业务列表页面
screen: Appointment,
navigationOptions: () => ({
header: null, //去除标题栏
headerBackTitle: null, //去除返回按钮
gesturesEnabled: true //是否可以使用手势来关闭此屏幕。在iOS上默认为true,在Android上默认为false
})
}
},{
initialRouteName:'HomeScreen',
initialRouteParams:{ //设置初始参数
key:'aaaaa',
key1:'bbbbb'
},
});
注意:createStackNavigator与createSwitchNavigator的区别。它两个作用大致相同。createStackNavigator具有堆栈功能,createSwitchNavigator不具有堆栈功能,createSwitchNavigator的目的是一次只显示一个屏幕。默认情况下,它不处理后退操作,并在您切换时,将路由重置为其默认状态。这是我们从身份验证流程中想要的确切行为。
我们进行了跳转配置后,当然就是如何使用了。
screen
您应用中的每个组件都会navigation
自动提供道具。prop包含各种便利功能,用于在路由的路由器上分派导航操作。
进行跳转的API https://reactnavigation.org/docs/en/navigation-prop.html
this.props.navigation
navigate - 转到另一个屏幕,找出它需要采取的行动
goBack - 关闭活动屏幕并向后移动
addListener - 订阅导航生命周期的更新
isFocused- true如果屏幕聚焦false则返回的功能
state - 当前路线
setParams - 改变路线的参数,传递参数
getParam - 获得具有后备的特定参数,获取参数
dispatch - 向路由器发送动作
dangerouslyGetParent - 返回父导航器的函数(如果有)
简单举例
我们可以使用this.props.navigation.navigate('要跳转的View名称')方式进行跳转,该跳转方式,会将跳转的页面存入栈顶部,当点击返回按键,或者调用this.props.navigation.goBack()方法时返回到上个页面。
我们如果想要回退到指定的页面,我们需要得到我们将要回退页面上一个页面的页面key进行回退,调用this.props.navigation.goBack(key)方式回退到指定的页面。
比如,有A、B、C、D四个页面。我从A使用this.props.navigation.navigate('B')跳转到了B页面,然后使用this.props.navigation.navigate('C')跳转到了C页面,然后又跳转到D页面,但是我想直接返回到A页面,如果我按返回键,则返回顺序是D > C > B > A。不是我想要的结果。我如果之间使用this.props.navigation.navigate('A')的方式跳转到A,那么我退出时,会出现A > D > C > B > A。这种情况(当然,有双击退出,强制退出操作不在考虑范围内),设计不太合理。我们可以使用this.props.navigation.goBack(key)这种方式进行返回,我们首先要得到我们要返回的页面的前一个页面的页面KEY,也就是A前面的页面B页面的KEY。
let HOME_KEY = this.props.navigation.state.key;//得到当前页面key
使用以上方式得到页面key后传入到D页面中的this.props.navigation.goBack(key)函数中。我们就能够返回到原页面。
使用this.props.navigation.navigate()方法也可以进行传值。
this.props.navigation.navigate('A', {
session: this.state.session,
ucid: this.state.ucid,
});
取值,包括初始化页面时的传递的初始值,也可以以这种方式取值
const { navigation } = this.props;
let value = navigation.getParam('key', ''); //得到Drawer页面传递的页面key
let value1 = navigation.getParam('key1', ''); //得到Drawer页面传递的页面key
底部导航栏 createBottomTabNavigator react-navigation为我们提供了底部导航栏与顶部导航栏的API,我们只做底部导航栏的讲解。
createBottomTabNavigator(RouteConfigs, BottomTabNavigatorConfig);
它同样有两个参数。RouteConfigs用法与createStackNavigator用法一样,不做讲解。但是,我们会将底部导航所需的View放在次参数中,因为,底部导航至少会有两个页面。
{//RouteConfigs
Home: {
screen: HomeStack,
},
Work: {
screen: WorkStack,
},
}
BottomTabNavigatorConfig,我们用来做一些底部导航栏样式的一些操作,比如,我们所点击的图标,图标颜色(选中状态颜色,未选中状态颜色),图标下方的字体等等。都在代码中添加了注释
//配置底部导航栏(标签栏),HomeScreen与WorkScreen页面
const bottomTabNavigator = createBottomTabNavigator({//RouteConfigs
Home: {
screen: HomeStack,
},
Work: {
screen: WorkStack,
},
}, {//BottomTavNavtigtorConfig
defaultNavigationOptions: ({ navigation }) => ({ //用于屏幕的默认导航选项
tabBarIcon: ({ focused, tintColor }) => //设置图标
getTabBarIcon(navigation, focused, tintColor),
tabBarLabel: navigation.state.routeName === 'Home' ? '首页' : '工作', //设置图标下方的字体
}),
tabBarOptions: { //设置图标的样式
activeTintColor: '#1E90FF', //活动选项卡的标签和图标颜色。选中时颜色
inactiveTintColor: '#979797' //非活动选项卡的标签和图标颜色。 未选中时颜色
},
});
//设置底部图片以及图片的状态改变
const getTabBarIcon = (navigation, focused, tintColor) => { //设置图标默认状态
const { routeName } = navigation.state;
if (routeName === 'Home') { //设置点击Home页面时,图标状态
return <Image style={{ //图标的样式
width: 25,
height: 25
}}
source={focused ? require('./image/tabbar_home_pressed.png') : require('./image/tabbar_home.png')} /> //返回选中与未选中不同状态时,图标的样式,颜色
} else if (routeName === 'Work') { //设置点击Work页面时,图标状态
return <Image style={{ 图标的样式
width: 25,
height: 25
}}
source={focused ? require('./image/tabbar_msg_pressed.png') : require('./image/tabbar_msg.png')} /> //返回选中与未选中不同状态时,图标的样式,颜色
}
};
createDrawerNavigator(RouteConfigs, DrawerNavigatorConfig);
同样的,俩个参数RouteConfigs, DrawerNavigatorConfig。
RouteConfigs
路由CONFIGS对象是从路由名称映射到一个路由配置,它告诉导航以呈现该路线什么。我们一般用来写侧拉框所在的页面。
{//RouteConfigs
Set: {//Set是固定名称
screen: bottomTabNavigator,
},
}
DrawerNavigatorConfig,用来配置侧拉框抽屉的一些默认设置
{
order: ['Set'],//routeNames数组,用于定义抽屉项目的顺序。
initialRouteName: 'Set',//初始路由的routeName。
drawerLockMode: 'unlocked',//设置是否响应手势
//'unlocked' 可以通过手势和代码 打开关闭抽屉
//'locked-closed' 抽屉关闭状态 不能通过手势打开 只能通过代码实现
//'locked-open' 抽屉打开状态 不能通过手势关闭 只能通过代码实现
drawerWidth: 300, //抽屉的宽度或返回的功能。
drawerPosition: 'left', //选项是left或right。默认是left位置。
useNativeAnimations: true, //启用原生动画。默认是true。
drawerBackgroundColor: '#FAFAFA', //使用抽屉背景获取某种颜色。默认是white。
//用于呈现抽屉内容的组件,例如导航项。收到navigation抽屉的道具。默认为DrawerItems
//用于自定义
contentComponent: props => {
return <Drawer {...props} />;
},
//配置抽屉内容 items相关
contentOptions: {
// items: [OtherScreen],//可以修改或覆盖路由数组 不知道干嘛用的
// activeItemKey: 'AppInfo', //识别活动路线的关键 也不知道干嘛用的
activeTintColor: 'white', //活动标签的标签和图标颜色
activeBackgroundColor: 'blue', //活动标签的背景颜色
inactiveTintColor: 'black', //非活动标签的标签和图标颜色
inactiveBackgroundColor: 'red', //非活动标签的背景颜色
// //按下项目时要调用的函数 不知道是否使用错误 一直没反应
//github上面有答案 在自定义视图的时候 会有用
// onItemPress(route) {
// console.log('onItemPress'+route);
// },
// itemsContainerStyle: '', //内容部分的样式对象
// itemStyle: '', //单个项目的样式对象,可以包含图标和 / 或标签
// labelStyle: '', //Text当标签是字符串时,样式对象在内容部分内覆盖样式
// activeLabelStyle: '', //Text当标签是字符串(与之合并labelStyle)时,样式对象覆盖活动标签的样式
// inactiveLabelStyle: '', //Text当标签是字符串(与之合并labelStyle)时,样式对象覆盖非活动标签的样式
// iconContainerStyle: '', //样式对象以覆盖View图标容器样式。
}
}
重点:
//用于自定义
contentComponent: props => {
return <Drawer {...props} />;
},
我们用该方法,可以将抽屉视图进行自定义。也就是说。我们可以在此页面编写抽屉视图。Drawer就是我的抽屉页面的视图。完全可以按照自己想要的效果进行布局。
this.props.navigation.openDrawer();//打开抽屉
this.props.navigation.closeDrawer();//关闭抽屉
我们可以在抽屉所在的页面中调用以上方法,进行打开或者关闭抽屉的动作。当然,也可以滑动屏幕来打开或关闭抽屉。
关于react-navigation的使用,我还远远未发掘出来,这只是它的一部分,包括它的生命周期,与RN的生命周期的对应,对于它的生命周期的处理。不过,这已经足够开发出一个优秀的App了。希望以后会更加熟练的使用react-navigation吧。