一、前言
公司需要做一款app。因为我本身是做前端的,所以技术栈选择了react-native
因为我之前有一些做小程序与Vue的经验,所以在接到这个任务时,我大概从下面几方面的问题去考虑该怎样去做这个app
-
路由管理
小程序在
app.json
中,pages放置全部的路由,在tabBar中放置所有BottomTabBar的路由,并且使用wx.navigateTo跳转普通页面,使用wx.switchTab跳转tabBar页面那么react-native是怎么去处理普通页面的路由和tabBar页面的路由的呢?
小程序的路由API除了跳转tabBar页面是不能带参数的,其他都是可以在路径后面带参数
**那么react-native是怎么在跳转路由时携带参数呢 **
Vue中有嵌套路由的概念
react-native是否有类似的概念呢
-
状态管理
Vue有Vuex可以实现全局的状态管理,react有redux,
**在react-native中应该如何去处理呢 **
react-native状态管理的数据持久化又应该怎么做呢
-
网路请求
react-native是怎么实现网络请求的
是否可以使用第三方库axios
-
生命周期,钩子函数
小程序和Vue都有生命周期函数,用来做特定时期的特定动作
那么react-native是否有生命周期函数呢
-
调用硬件功能
react-native怎么去调用手机的摄像头
react-native怎么去获取用户的相片
react-native怎么去获取用户授权等
根据综上问题去学习react-native,这篇文章便是来总结react-native是怎么编写路由的
二、路由栈
我会使用react navigation 4.x
的库,这是官网的网址https://reactnavigation.org/docs/zh-Hans/4.x/getting-started.html
怎么安装,官网写的非常详细,这里不赘述
RN中的路由是一个栈的概念,如下
当我们从首页点击到设备页,再点击到设备详情页时,就是不断往栈中加入路由,返回时,也是先把设备详情页从栈中拿掉,再拿设备页,直到剩下首页
三、创建路由栈
createStackNavigator可以创建路由栈
npm install react-navigation-stack @react-native-community/masked-view
安装依赖
import {createStackNavigator} from "react-navigation-stack"
const AppNavigator = createStackNavigator({
//路由的名字:路由的页面
Home:HomePage,// HomePage 需要自己编写并导入
Device:DevicePage,
DeviceDetail:DeviceDetailPage,
// 需要注意,上面引入的页面的顺序不会影响路由栈的显示
},{
// 初始化的路由页面是什么
initialRouteName:"Home"//初始化页面显示HomePage
})
四、路由的跳转
我们创建的AppNavigator会给HomePage,DevicePage,DeviceDetailPage
页面组件传递 navigation
这个prop,我们可以用navigation
来实现页面的跳转
import React,{Component} from "react"
export default class HomePage extends Component{
render(){
<View>
<Text>首页</Text>
<Button
title="跳转到设备页"
onPress={()=>{
this.props.navigation.navigate("Device")
}}
/>
</View>
}
}
路由跳转的API
this.props.navigation.navigate("组件路由名字")
this.props.navigation.push('组件路由名字')
this.props.navigation.goBack('组件路由名字')
//goBack()括号内可不写,如果组件路由名字和上个页面的路由名字不一致,则不会跳转,
this.props.navigation.popToTop('组件路由名字')
//popToTop()括号内可不写,如果组件路由名字和最上层页面的路由名字不一致,则不会跳转,
navigate: 会判断栈中有没有这个组件,如果有则回到那个页面,如果没有则创建一个新的组件进行压栈展示
push:创建一个新的组件 ,进行压栈展示
goBack:返回上一个页面
popToTop:回到首页组件
页面之间传递参数
this.props.navigation.navigate方法可以传递参数到下一个页面,如下面代码所示
<View>
<Text>首页</Text>
<Button
title="跳转到详情页"
onPress={()=>this.props.navigation.navigate('Details',{
newsId:"100",
newsName:"新闻1",
newsTag:"重要"
})}
></Button>
</View>
页面接收参数
<Text>参数1:{this.props.navigation.getParam("newsId")}</Text>
<Text>参数2:{this.props.navigation.getParam("newsName")}</Text>
<Text>参数3:{this.props.navigation.getParam("newsTag")}</Text>
<Text>所有参数:{this.props.navigation.state.params}</Text>
五、创建BottomTabBar
npm install react-navigation-tabs
安装依赖
import {createBottomTabNavigator,BottomTabBar} from "react-navigation-tabs"
import Icons from "react-native-vector-icons/Feather"
const AppBottomTabBar = createBottomTabNavigator({
Home:{
screen:HomePage,
navigationOptions:{
title:"首页",//设定标题
//显示的图标
tabIcon:({tintColor,focused})=>(
<Icons
name={'home'}
size={26}
style={{color:tintColor}}
/>
)
}
},
Device:DevicePage,
Message:MessagePage,
Mine:MinePage
},{
// 底部标签栏要展示的组件
tabBarComponent:props=>(
// activeTintColor为选中时的颜色
<BottomTabBar {...props} activeTintColor="#34b5ff"/>
)
})
react-native有配套的icon库https://github.com/oblador/react-native-vector-icons,
npm install --save react-native-vector-icons
安装依赖
react-native link react-native-vector-icons
让图标能在ios和android上显示
六、tabBar路由和普通页面路由组合起来
有个需求如下:
在欢迎页面显示一秒后跳转到登陆页面,登陆成功则显示tabBar页面,tabBar页面可以跳转到其他页面
因为路由栈是连续的,我不希望在登陆成功后,tabBar页面还能返回到登陆页面
createSwitchNavigator
SwitchNavigator 可以帮助我们
SwitchNavigator 的用途是一次只显示一个页面。 默认情况下,它不处理返回操作,并在你切换时将路由重置为默认状态。 这是我们希望从身份验证流程获得的确切行为。
import {createSwitchNavigator,createAppContainer} from "react-navigation"
import {createStackNavigator} from "react-navigation-stack"
const InitNavigator = createStackNavigator({
Welcome:WelcomePage,
Login:LoginPage,
})
const MainNavigator = createStackNavigator({
Home:{// Home即是tabBar页面
screen:BottomTabPage,
navigationOptions:{
headerShown:false
}
},
DeviceDetail:DeviceDetailPage,
})
export const RootNavigator = createAppContainer(createSwitchNavigator({
Init:InitNavigator,
Main:MainNavigator
}))
tabBar页面是创建BottomTabBar,并返回BottomTabBar页面的组件
// BottomTabPage
import React,{Component} from "react"
import Icons from "react-native-vector-icons/Feather"
import {createBottomTabNavigator,BottomTabBar} from "react-navigation-tabs"
import {createAppContainer} from "react-navigation"
import {
StyleSheet,
Image,
} from "react-native"
import HomePage from "../page/HomePage"
import DevicePage from "../page/DevicePage"
import MinePage from "../page/MinePage"
import MessagePage from "../page/MessagePage"
const Tabs = {
Home:{
screen:HomePage,
navigationOptions:{
title:"首页",
tabBarIcon:({tintColor,focused})=>(
<Icons
name={'home'}
size={26}
style={{color:tintColor}}
/>
)
}
},
Device...,
Message...,
Mine...,
}
export default class MainTabNavigator extends Component{
_Navigator(){
const {Home,Device,Message,Mine} = Tabs;
const tabs={Home,Device,Message,Mine}
if(!this.navigator){
this.navigator=createAppContainer(createBottomTabNavigator(
tabs,{
tabBarComponent:props=>
<BottomTabBar {...props} activeTintColor="#34b5ff"/>
}
))
}
return this.navigator
}
render(){
const TabNavigator = this._Navigator()
return <TabNavigator/>;
}
}
const styles = StyleSheet.create({
BottomTabBarIconImage:{
width:30,
height:30
}
})
总结现在的路由结构
当我在LoginPage登陆成功时,可以这样子跳转到home页面
this.props.navigation.navigate("main")//因为Home排序第一,所以跳转到main页面时会显示Home页面
Home页面如下
当我点击我的tab
时会跳转到MinePage,当想要从MinePage页面跳转到其他页面(个人信息页面等)时。却行不通了
为了解决这个问题,我们就必须要在Home页面时,就保存navigation
然后,在MinePage去使用
//NavigatiorUtil
export default class NavigatorUril{
static goPage(params,page){
// 在BottomTabBar页面接受navigation
const navigation = NavigationUtil.navigation
if(!navigation){
console.log("NavigationUtil.navigation can not be null")
return;
}
navigation.navigate(
page,
{
...params
}
)
}
}
// Home页面
import NavigationUtil from "../navigator/NavigationUtil"
export default class BottomTabPage extends Component{
render(){
NavigationUtil.navigation = this.props.navigation
return(
<View style={styles.wrapper}>
<MainTabNavigator/>
</View>
)
}
}
// MinePage
import NavigationUtil from "../navigator/NavigationUtil"
export default class MinePage extends Component {
render(){
return (
<View style={styles.wrapper}>
<Text style={styles.item}>我的</Text>
<TouchableHighlight
style={styles.button}
onPress={()=>{
NavigationUtil.goPage({},"DeviceGroupManager")
}}
>
<Text style={styles.btnText}>跳转个人信息</Text>
</TouchableHighlight>
</View>
)
}
}
七、创建TopBarNavigatior
createMaterialTopTabNavigator
import {createMaterialTopNavigator} from "react-navigation-tabs"
import {createAppContainer} from "react-navigation"
export default class HomePage extends Component {
_topTabBar(){
if(!this.topTabBar){
this.topTabBar = createAppContainer(createMaterialTopTabNavigator({
tab1:{
screen:HomeDevicePage,
navigationOptions:{
title:"家庭"
}
},
tab2:{
screen:SchoolDevicePage,
navigationOptions:{
title:"学校"
}
}
},{
tabBarOptions: {
tabStyle: styles.tabStyle,//选项卡等样式对象,
upperCaseLabel: false,//是否使标签大写,默认为true
scrollEnabled: true,//是否支持 选项卡滚动,默认false
style: {// 选项卡栏等样式对象
backgroundColor: "#fff",//TabBar 的背景颜色
height: 30,
},
indicatorStyle: styles.indicatorStyle,//标签指示器的样式
labelStyle: styles.labelStyle,//文字的样式
},
lazy: true
}))
}
return this.topTabBar
}
render(){
const TopTabBar = this._topTabBar()
return (
<View style={{flex:1,marginTop:30}}>
<TopTabBar/>
</View>
)
}
}
结语
如果文章中有错漏处,请看官们指正 如果觉得文章不错的话,请点个赞吧。
作者:胡志武
时间:2020/02/08