React Native中的路由的基本使用!

  • 官方文档

  • React Native中的路由功能是通过react-navigation这个组件来实现的,与react中的路由(react-router)两者之间是有差异的,因为RN是运行在APP中的,RN当中主要用到的路由有以下四种

  1. stack栈路由 (基本路由)
  2. BottomTab 底部标签路由 (底部导航)
  3. drawer 抽屉路由 (左右划出菜单)
  4. MaterialTopTab 顶部标签路由 (顶部导航)

安装路由,相关依赖以及初始化配置

  1. 下载路由
npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view
  1. 下载路由回收(普通屏幕和刘海屏)
npm i react-native-screens react-native-safe-area-context
  1. 处理手势
npm i react-native-gesture-handler
  1. 给整个项目添加头部组件以及导航容器
  1. 使用import 'react-native-gesture-handler'添加到项目头部(如index.js或者App.js)
  2. 在整个项目的入口文件中,使用NavigationContainer包裹整个项目(如在index.js或者App.js中1)
  • App.js
import 'react-native-gesture-handler';
import * as React from 'react';
import { NavigationContainer } from '@react-navigation/native';
// import { Text, StyleSheet, View, Switch, StatusBar } from 'react-native'
import RnRuoter from './src/RnRouter' // 引入路由配置页面

export default function App() {
return (
// 使用 NavigationContainer 包裹路由配置页面
<NavigationContainer>
<RnRuoter />
</NavigationContainer>
);
}

const styles = StyleSheet.create({})

stack 栈路由

  • 官方文档

  • RN当中是没有类似浏览器的history对象的,这就意味着我们我们无法使用浏览器的那一套前进后退的路由操作,因此我们要想在RN当中做路由跳转,就需要先将我们的路由页面声明在Stack当中,随后使用RN路由的方法navigator('路由名')来实现跳转

Navigator的基本属性(Stack.navigator作用于整个导航)

  1. initialRouteName(用于指向默认路由页,即默认加载的路由页面)
  2. headerMode(用于声明头部信息,一般有三种效果: float(ios), screen(Android), none(不显示头部))

Screen的基本属性(Stack.screen仅作用于当前页面)

  1. options(一般属性基本是设置在options属性里面的)
    1. title: 显示标题
    2. headerTitleStyle: 标题样式
    3. headerStyle: 头部样式
    4. headerLeft: 声明页头左侧内容
    5. headerRight: 声明页头右侧内容
    6. headerTintColor: 标题颜色

效果如下:

image

安装

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' // 路由跳转器

// 通过useNavigation创建出一个导航器 同样可以实现路由跳转
const myNavigation = useNavigation()

// 1. 创建栈路由
const Stack = createStackNavigator();

// 2. 创建两个路由页面(组件)
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 (
/*
由于我们在App.js中已经配置了 NavigationContainer
,因此这里就不需要再使用NavigationContainer包裹了
*/
<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路由

  • 官方文档

  • 配置方法基本与上面的栈路由是一致的,只不过不再需要再在路由组件中添加额外的按钮用于路由跳转了,我们可以直接使用底部的tab进行页面的跳转

安装

npm i @react-navigation/bottom-tabs

效果:

image

基本使用:

  • 路由组件
// 引入路由创建函数
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
// 引入路由容器
import { NavigationContainer } from '@react-navigation/native';
// 创建Tab路由
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>
)
}

// 配置Tab路由
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

效果:

image

基本属性:

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";
// 创建Drawer路由
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>
)
}

// 配置Drawer路由
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>
);
}

路由传参

实现方法:

  1. 传递参数:
// 传递参数方法如下
navigation.navigate('路由名字',{key:123})
  1. 接收参数
// 1. 类组件
this.props.route.params.key

// 2. 函数式组件
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 }) {
/* 2. Get the param */
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>
);
}