react-navigation 6.x版本的安装、传参、navigator的使用等介绍(part2)。
目前react-navigation的官方文档已经更新到了6.x
版本,在官方文档中对于其基本的使用方法也有所介绍,但是对于一些比较复杂的使用场景,或者传参等细节问题并没有给出详细的解决方案。
在这篇文章中,我将介绍Native Stack Navigator
的使用以及Drawer Navigation
的使用。
Native Stack Navigator
基本用法
如果不想显示任何导航栏,stack navigator
无疑是个最好的选择,这是最基本的页面导航,它维护了一个栈结构,进入一个页面相当于在栈里压入了一个页面,返回操作相当于在栈中弹出一个页面。在官方文档给出了基本的用法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| import * as React from 'react'; import { Button, View } from 'react-native'; import { NavigationContainer } from '@react-navigation/native'; import { createNativeStackNavigator } from '@react-navigation/native-stack';
function HomeScreen({ navigation }) { return ( <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}> <Button title="Go to Profile" onPress={() => navigation.navigate('Profile')} /> </View> ); }
function ProfileScreen({ navigation }) { return ( <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}> <Button title="Go to Notifications" onPress={() => navigation.navigate('Notifications')} /> <Button title="Go back" onPress={() => navigation.goBack()} /> </View> ); }
function NotificationsScreen({ navigation }) { return ( <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}> <Button title="Go to Settings" onPress={() => navigation.navigate('Settings')} /> <Button title="Go back" onPress={() => navigation.goBack()} /> </View> ); }
function SettingsScreen({ navigation }) { return ( <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}> <Button title="Go back" onPress={() => navigation.goBack()} /> </View> ); }
const Stack = createNativeStackNavigator();
function MyStack() { return ( <Stack.Navigator> <Stack.Screen name="Home" component={HomeScreen} /> <Stack.Screen name="Notifications" component={NotificationsScreen} /> <Stack.Screen name="Profile" component={ProfileScreen} /> <Stack.Screen name="Settings" component={SettingsScreen} /> </Stack.Navigator> ); }
export default function App() { return ( <NavigationContainer> <MyStack /> </NavigationContainer> ); }
|
这里createNativeStackNavigator
创建了一个stack
,在不同的页面之间,点击Button
触发navigation.navigate
导航到特定名字的页面,或者触发navigation.goBack
返回上一级页面,如果我们使用的是真机的话,后退手势也可以返回上一级页面。实现的效果如下:
同样,这里默认还是会显示header的,如果我们不想显示header的话,也可以在Stack.Navigator
里面添加headerShown: false
属性,原则上第一个页面是打开的默认页面,我们也可以使用initialRouteName
指定默认页面,如下所示:
1 2 3 4 5 6 7 8 9
| <Stack.Navigator initialRouteName="Notifications"{% raw %} screenOptions={{headerShown: false}}{% endraw %} > <Stack.Screen name="Home" component={HomeScreen} /> <Stack.Screen name="Notifications" component={NotificationsScreen} /> <Stack.Screen name="Profile" component={ProfileScreen} /> <Stack.Screen name="Settings" component={SettingsScreen} /> </Stack.Navigator>
|
进阶:不同navigator之间的嵌套
如果我们希望做一个购物网站,浏览页底部显示tab导航栏,详情页面等一些页面不显示底部的tab导航栏,那我们可以将tab导航栏包裹后作为一个stack.screen
,而其他不需要显示底部tab导航栏的也作为同级的stack.screen
,示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| import {createBottomTabNavigator} from '@react-navigation/bottom-tabs'; import {NavigationContainer} from '@react-navigation/native'; import {createNativeStackNavigator} from '@react-navigation/native-stack';
const Tab = createBottomTabNavigator(); const Route = createNativeStackNavigator();
export function TabWrapper() { return ( <Tab.Navigator> <Tab.Screen name="首页" component={HomeScreenWrapper} options={{headerShown: false}} /> ..... </Tab.Navigator> ); }
export default function App() { return ( <NativeBaseProvider> <NavigationContainer> <Route.Navigator initialRouteName="Welcome" screenOptions={{headerShown: false}}> <Route.Screen name="Detail" component={DetailScreen} /> ...... <Route.Screen name="TabWrapper" component={TabWrapper} options={{headerShown: false}} /> </Route.Navigator> </NavigationContainer> </NativeBaseProvider> ); }
|
Drawer Navigation
基本用法
Drawer Navigation
实现了一个左侧的可收起导航栏,基本使用方法可见官方文档
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| import * as React from 'react'; import { Button, View } from 'react-native'; import { createDrawerNavigator } from '@react-navigation/drawer'; import { NavigationContainer } from '@react-navigation/native';
function HomeScreen({ navigation }) { return ( <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}> <Button onPress={() => navigation.navigate('Notifications')} title="Go to notifications" /> </View> ); }
function NotificationsScreen({ navigation }) { return ( <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}> <Button onPress={() => navigation.goBack()} title="Go back home" /> </View> ); }
const Drawer = createDrawerNavigator();
export default function App() { return ( <NavigationContainer> <Drawer.Navigator useLegacyImplementation initialRouteName="Home"> <Drawer.Screen name="Home" component={HomeScreen} /> <Drawer.Screen name="Notifications" component={NotificationsScreen} /> </Drawer.Navigator> </NavigationContainer> ); }
|
在Drawer Navigator
中也可以用触发navigation.navigate
导航到特定名字的页面,或者触发navigation.goBack
返回上一级页面,或者使用真机回退手势实现页面的回退;和Tab Navigator
一样,同样也可以将Drawer Navigator
嵌套到Stack Navigator
。样例的效果如下:
进阶:参数传递
假如我们希望使用Drawer Navigator
实现一个分类页面,渲染效果基本相同,但是传递的参数不同导致内容不同,为了不简单地将渲染效果的代码简单复制粘贴多遍,造成大量代码冗余,我们可以使用一个SwitchScreen{i}
作为中间桥梁,不同的SwitchScreen
向最终渲染效果的RenderScreen
传递不同的参数,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| import React, {useState} from 'react'; import {ActivityIndicator, Button, View} from 'react-native'; import {createDrawerNavigator} from '@react-navigation/drawer';
const RenderScreen = props => { console.log('RenderScreen props:', props);
React.useEffect(() => { .... } }, []);
return ( ..... ); };
function SwitchScreen1() { return <RenderScreen props="默认" />; }
function SwitchScreen2() { return <RenderScreen props="类别1" />; }
function SwitchScreen3() { return <RenderScreen props="类别2" />; }
function SwitchScreen4() { return <RenderScreen props="类别3" />; }
function SwitchScreen5() { return <RenderScreen props="类别4" />; }
function SwitchScreen6() { return <RenderScreen props="类别5" />; }
const Drawer = createDrawerNavigator();
export default function BrowseScreen() { return ( <Drawer.Navigator useLegacyImplementation initialRouteName="默认" drawerBackgroundColor="#fda4af"> <Drawer.Screen name="默认" component={SwitchScreen1} /> <Drawer.Screen name="类别1" component={SwitchScreen2} /> <Drawer.Screen name="类别2" component={SwitchScreen3} /> <Drawer.Screen name="类别3" component={SwitchScreen4} /> <Drawer.Screen name="类别4" component={SwitchScreen5} /> <Drawer.Screen name="类别5" component={SwitchScreen6} /> </Drawer.Navigator> );
|