React Native
中的路由的基本使用!
官方文档
React Native
中的路由功能是通过react-navigation
这个组件来实现的,与react
中的路由(react-router
)两者之间是有差异的,因为RN
是运行在APP
中的,RN
当中主要用到的路由有以下四种
stack
栈路由 (基本路由
)
BottomTab
底部标签路由 (底部导航
)
drawer
抽屉路由 (左右划出菜单
)
MaterialTopTab
顶部标签路由 (顶部导航
)
安装路由,相关依赖以及初始化配置
- 下载路由
npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view
|
- 下载路由回收(普通屏幕和刘海屏)
npm i react-native-screens react-native-safe-area-context
|
- 处理手势
npm i react-native-gesture-handler
|
- 给整个项目添加头部组件以及导航容器
- 使用
import 'react-native-gesture-handler'
添加到项目头部(如index.js或者App.js
)
- 在整个项目的入口文件中,使用
NavigationContainer
包裹整个项目(如在index.js
或者App.js
中1)
import 'react-native-gesture-handler'; import * as React from 'react'; import { NavigationContainer } from '@react-navigation/native';
import RnRuoter from './src/RnRouter'
export default function App() { return ( <NavigationContainer> <RnRuoter /> </NavigationContainer> ); }
const styles = StyleSheet.create({})
|
stack
栈路由
官方文档
在RN
当中是没有类似浏览器的history
对象的,这就意味着我们我们无法使用浏览器
的那一套前进后退的路由操作,因此我们要想在RN
当中做路由跳转,就需要先将我们的路由页面声明在Stack
当中,随后使用RN
路由的方法navigator('路由名')
来实现跳转
Navigator
的基本属性(Stack.navigator
作用于整个导航)
initialRouteName
(用于指向默认路由页,即默认加载的路由页面)
headerMode
(用于声明头部信息,一般有三种效果: float
(ios
), screen
(Android
), none
(不显示头部
))
Screen
的基本属性(Stack.screen
仅作用于当前页面)
options
(一般属性基本是设置在options
属性里面的)
title
: 显示标题
headerTitleStyle
: 标题样式
headerStyle
: 头部样式
headerLeft
: 声明页头左侧内容
headerRight
: 声明页头右侧内容
headerTintColor
: 标题颜色
效果如下:
安装
npm i @react-navigation/native-stack
|
基本使用:
import { StyleSheet, Text, View } from 'react-native' import React from 'react' import { createStackNavigator } from '@react-navigation/stack'; import { useNavigation } from '@react-navigation/native'
const myNavigation = useNavigation()
const Stack = createStackNavigator();
const Home = (props)=>{ return ( <View style={{ flexDirection:'row', justifyContent:'center', alignItems:'center', }}> <Text>首页</Text> <Button title={'跳转新闻页面'} onPress={()=>{ // 使用父组件传过来的 navigation 实现跳转('路由页面名字') props.navigation.navigate('News') }}/> </View> ) }
const News = (props)=>{ return ( <View style={{ flexDirection:'row', justifyContent:'center', alignItems:'center', }}> <Text>新闻</Text> <Button title={'跳转首页'} onPress={()=>{ // 使用父组件传过来的 navigation 实现跳转('路由页面名字') props.navigation.navigate('Home') }}/> </View> ) }
export default function RnRouter() { return (
<Stack.Navigator initialRouteName='News' // 设置默认显示的页面(新闻) headerMode={'float'} // 顶部显示样式(ios) screenOptions={{ title:'Home', // 设置标题栏标题内容 headerStyle: { backgroundColor: '#ff6600' // 设置标题栏背景颜色 }, headerTintColor: '#ffffff', // 标题文字颜色 headerTitleAlign: 'center', // 标题文字居中方式 headerShown: false // 是否显示标题栏 }} > {/* 没有配置的情况下第一个路由Stack.Screen显示为首页 */}
{/* 路由写法1 */} <Stack.Screen name='Home' component={ Home } options={{ title='首页',// 顶部标题 headerStyle:{// 顶部样式 backgroundColor:'yellowgreen' }, headerRight: ()=>{ // 顶部右边渲染 <TouchableOpacity onPress={()=>{ alert('hello') }}> <Text>hello</Text> </TouchableOpacity> } }} />
{/* 路由写法2 (必须为函数返回一个React组件并且需要传入props) */} <Stack.Screen name='News'> {props => <News {...props}/>} </Stack.Screen> </Stack.Navigator> ) }
const styles = StyleSheet.create({})
|
导航器的跳转方法:
navigation.goBack() navigation.navigate() navigation.push() navigation.replace()
|
BottomTab
路由
安装
npm i @react-navigation/bottom-tabs
|
效果:
基本使用:
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
import { NavigationContainer } from '@react-navigation/native';
const Tab = createBottomTabNavigator();
const Home = (props)=>{ return ( <View style={{ flexDirection:'row', justifyContent:'center', alignItems:'center', }}> <Text>首页</Text> </View> ) }
const News = (props)=>{ return ( <View style={{ flexDirection:'row', justifyContent:'center', alignItems:'center', }}> <Text>新闻</Text> </View> ) }
function TabBar(){ return ( <Tab.Navigator // 展示图标(这里用按钮替代) screenOptions={({route})=>{// 这里的route可以获取当前点击到的路由实例 tabBarIcon:({focused, color, size})=>{ let iconName if(route.name === 'Home'){ iconName = '首页' }else if(route.name === 'News'){ iconName = '新闻' } return <Button title={iconName} size={size} color={color}/> } }}
tabBarOptions={{//设置图标颜色 activeTintColor:'yellowgreen',//点击状态时的颜色 inactiveTintColor:'gary',//非点击状态时的颜色 }} > <Tab.Screen name={"Home"} options={{title:"首页"}} component={Home} /> <Tab.Screen name={"News"} options={{title:"新闻"}} component={News} /> </Tab.Navigator> ) } export default function (){ return ( <NavigationContainer> <TabBar /> </NavigationContainer> ) }
|
Drawer
导航
官方文档
这里的Drawer
导航相当于左滑右滑菜单
安装:
npm install @react-navigation/drawer
|
效果:
基本属性:
navigator
属性:
1. `drawerPosition`: 菜单的显示位置(弹出位置), `left`(默认) |`right`
1. `drawerType`: 菜单弹出的动画效果, `front` | `back` | `slide`(滑动弹出) | `permanent`
1. `drawerStyle`: 菜单样式
4. `drawerContentOptions`: 选中的菜单样式
1. `activeTintColor`: 当前选中的菜单字体样式
2. `itemStyle`: 所有菜单选项的样式
screen
属性:
1. `options`
1. `title`:声明菜单标题
2. `drawerLabel`: 相较于`title`子恩那个声明简单的文字,它可以返回复杂的组件,例如按钮
3. `drawerIcon`: 返回图标的函数
4. `headerShown`: 是否显示`header`布尔值,默认不显示
5. `headerRight/Left`: 函数,声明左右侧的显示内容
基本使用:
import { createDrawerNavigator } from "@react-navigation/drawer";
import { NavigationContainer } from '@react-navigation/native'; import { Button,Text,View } from "react-native";
const Drawer = createDrawerNavigator();
const Home = (props) => { return ( <View style={{ flexDirection: 'row', justifyContent: 'center', alignItems: 'center', }}> <Text>首页</Text> {/* openDrawer为点击打开抽屉菜单 */} <Button title={'点击打开菜单'} onPress={() => { props.navigation.openDrawer() }} /> {/* toggleDrawer为点击打开抽屉菜单,点击关闭 */} <Button title={'点击打开菜单,点击关闭'} onPress={() => { props.navigation.toggleDrawer() }} /> </View> ) }
const News = (props) => { return ( <View style={{ flexDirection: 'row', justifyContent: 'center', alignItems: 'center', }}> <Text>新闻</Text> <Button title={'点击跳转到首页'} onPress={() => { props.navigation.navigate('Home') }} /> </View> ) }
function Drawer() { return ( <Drawer.Navigator drawerStyle={{/* 设置菜单样式 */}} drawerPosition={/* 设置菜单弹出位置 */} drawerType={/* 设置菜单弹出样式 */} drawerContentOptions={ // 设置可点击菜单样式 activeTintColor:'red',// 设置点击了的菜单样式 itemStyle:{/* 所有单个菜单样式 */} } > <Drawer.Screen options={ title:'首页',// 设置菜单标题 drawerIcon: ({focused,color,size})=>{ let iconNane iconNane = focused? 'home':'home-outline'// 判断当前是否点击返回对应的图标 return <Ionicons name={iconNane} size={size} color={color}/> } } name={"Home"} options={{ title: "首页" }} component={Home} /> <Drawer.Screen name={"News"} options={{ title: "新闻" }} component={News} /> </Drawer.Navigator> ) } export default function () { return ( <NavigationContainer> <Drawer /> </NavigationContainer> ) }
|
路由的嵌套
官方示例:
function Home() { return ( <Tab.Navigator> <Tab.Screen name="Feed" component={Feed} /> <Tab.Screen name="Messages" component={Messages} /> </Tab.Navigator> ); }
function App() { return ( <NavigationContainer> <Stack.Navigator> <Stack.Screen name="Home" component={Home} options={{ headerShown: false }} /> <Stack.Screen name="Profile" component={Profile} /> <Stack.Screen name="Settings" component={Settings} /> </Stack.Navigator> </NavigationContainer> ); }
|
路由传参
实现方法:
- 传递参数:
navigation.navigate('路由名字',{key:123})
|
- 接收参数
this.props.route.params.key
route.params.key
|
官方示例代码:
function HomeScreen({ navigation }) { return ( <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}> <Text>Home Screen</Text> <Button title="Go to Details" onPress={() => { /* 1. Navigate to the Details route with params */ navigation.navigate('Details', { itemId: 86, otherParam: 'anything you want here', }); }} /> </View> ); }
function DetailsScreen({ route, navigation }) { const { itemId, otherParam } = route.params; return ( <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}> <Text>Details Screen</Text> <Text>itemId: {JSON.stringify(itemId)}</Text> <Text>otherParam: {JSON.stringify(otherParam)}</Text> <Button title="Go to Details... again" onPress={() => navigation.push('Details', { itemId: Math.floor(Math.random() * 100), }) } /> <Button title="Go to Home" onPress={() => navigation.navigate('Home')} /> <Button title="Go back" onPress={() => navigation.goBack()} /> </View> ); }
|