React Navigation:栈、标签与抽屉导航

FreeGuideOnline 最新 2026-06-17

React Navigation 完全指南:栈、标签与抽屉导航

React Navigation 是 React Native 生态中最受欢迎的导航解决方案。它提供了一套完整的导航模式,包括栈导航标签导航抽屉导航,能够轻松构建结构清晰、用户体验良好的移动应用。本教程将从零开始,带你掌握这三种核心导航器的用法及其组合技巧。

前置准备

在开始之前,确保你的项目已经初始化好 React Native 环境。如果还没有,可以使用 npx react-native init 创建。接着安装核心库和依赖:

npm install @react-navigation/native
npm install react-native-screens react-native-safe-area-context

对于 iOS,还需要执行 cd ios && pod install。之后根据要使用的导航器类型,分别安装对应的包:

npm install @react-navigation/native-stack   # 栈导航
npm install @react-navigation/bottom-tabs    # 底部标签导航
npm install @react-navigation/drawer         # 抽屉导航

导航容器与基础结构

所有导航器必须包裹在 NavigationContainer 内,它负责管理导航树和应用状态。

import { NavigationContainer } from '@react-navigation/native';

export default function App() {
  return (
    <NavigationContainer>
      {/* 在这里放置你的导航器 */}
    </NavigationContainer>
  );
}

下面我们逐一拆解三种导航器。

栈导航器(Native Stack)

栈导航器使用“屏幕堆栈”模型,新屏幕推入栈顶,返回时弹出。createNativeStackNavigator 利用原生动画和手势,性能优于 JS 实现的 Stack Navigator。

创建基础栈

import { createNativeStackNavigator } from '@react-navigation/native-stack';

const Stack = createNativeStackNavigator();

function HomeScreen({ navigation }) {
  return (
    <View>
      <Button
        title="前往详情"
        onPress={() => navigation.navigate('Details', { itemId: 42 })}
      />
    </View>
  );
}

function StackNavigator() {
  return (
    <Stack.Navigator initialRouteName="Home">
      <Stack.Screen name="Home" component={HomeScreen} />
      <Stack.Screen name="Details" component={DetailsScreen} />
    </Stack.Navigator>
  );
}
  • initialRouteName 指定默认显示的屏幕。
  • 通过 navigation.navigate('RouteName', params) 携带参数跳转。
  • 目标屏幕可通过 route.params 获取参数。

自定义栈标题栏

Stack.Navigator 支持全局样式,Stack.Screen 可针对单个屏幕配置。

<Stack.Navigator
  screenOptions={{
    headerStyle: { backgroundColor: '#f4511e' },
    headerTintColor: '#fff',
    headerTitleStyle: { fontWeight: 'bold' },
  }}
>
  <Stack.Screen
    name="Home"
    component={HomeScreen}
    options={{ title: '首页' }}
  />
</Stack.Navigator>

常用的 screenOptions 属性包括 headerShown: false 可以隐藏标题栏,这在构建自定义导航栏时非常有用。

编程式导航与回退

  • navigation.goBack() 返回上一页。
  • navigation.popToTop() 回到栈底。
  • navigation.push('Route') 即使该路由已在栈中,也会生成新实例。

标签导航器(Bottom Tabs)

底部标签导航是最常见的移动导航模式,适用于主功能模块之间的切换。React Navigation 提供 createBottomTabNavigator

创建底部标签栏

import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';

const Tab = createBottomTabNavigator();

function TabNavigator() {
  return (
    <Tab.Navigator
      screenOptions={({ route }) => ({
        tabBarIcon: ({ focused, color, size }) => {
          let iconName;
          if (route.name === 'Home') {
            iconName = focused ? 'home' : 'home-outline';
          } else if (route.name === 'Profile') {
            iconName = focused ? 'person' : 'person-outline';
          }
          return <Ionicons name={iconName} size={size} color={color} />;
        },
        tabBarActiveTintColor: 'tomato',
        tabBarInactiveTintColor: 'gray',
      })}
    >
      <Tab.Screen name="Home" component={HomeScreen} />
      <Tab.Screen name="Profile" component={ProfileScreen} />
    </Tab.Navigator>
  );
}
  • 使用 tabBarIcon 渲染图标,通常配合 @expo/vector-iconsreact-native-vector-icons
  • tabBarActiveTintColortabBarInactiveTintColor 控制激活与非激活颜色。
  • 如果某个标签不需要导航栏头,可设置 options={{ headerShown: false }}

自定义选项卡外观

通过 tabBarStyle 可以调整标签栏背景色、高度、边框等:

<Tab.Navigator
  screenOptions={{
    tabBarStyle: { backgroundColor: '#6200ee', borderTopWidth: 0 },
    tabBarLabelStyle: { fontSize: 12 },
  }}
>

抽屉导航器(Drawer)

抽屉导航从屏幕侧边滑出菜单,适合功能多、层级深的应用。createDrawerNavigator 默认附带手势和遮罩。

创建抽屉导航

import { createDrawerNavigator } from '@react-navigation/drawer';

const Drawer = createDrawerNavigator();

function DrawerNavigator() {
  return (
    <Drawer.Navigator
      screenOptions={{
        drawerActiveTintColor: '#e91e63',
        headerTintColor: '#fff',
        headerStyle: { backgroundColor: '#e91e63' },
      }}
    >
      <Drawer.Screen name="Home" component={HomeScreen} />
      <Drawer.Screen name="Notifications" component={NotificationsScreen} />
    </Drawer.Navigator>
  );
}
  • 自定义抽屉内容可使用 drawerContent 属性,传入自定义组件。
  • drawerType 可以设置为 'front''back''slide' 控制动画。
  • edgeWidthswipeEnabled 控制左滑手势的触发范围和开关。

自定义抽屉菜单

<Drawer.Navigator
  drawerContent={(props) => <CustomDrawerContent {...props} />}
>
  {/* ... */}
</Drawer.Navigator>

CustomDrawerContent 中,你可以使用 DrawerContentScrollViewDrawerItemList 构建定制化的菜单项。

嵌套导航器

实际项目中很少只使用一种导航器,通常需要嵌套。例如:一个包含底部标签的应用,每个标签页内部有自己的栈导航。

典型结构示例

// 每个标签页的内部栈导航
function HomeStack() {
  return (
    <Stack.Navigator>
      <Stack.Screen name="HomeMain" component={HomeScreen} />
      <Stack.Screen name="Details" component={DetailsScreen} />
    </Stack.Navigator>
  );
}

// 主标签导航器
function AppTabs() {
  return (
    <Tab.Navigator screenOptions={{ headerShown: false }}>
      <Tab.Screen name="HomeTab" component={HomeStack} />
      <Tab.Screen name="ProfileTab" component={ProfileScreen} />
    </Tab.Navigator>
  );
}

// 根导航器可以再包裹一个抽屉
function RootNavigator() {
  return (
    <Drawer.Navigator>
      <Drawer.Screen name="Main" component={AppTabs} />
      <Drawer.Screen name="Settings" component={SettingsScreen} />
    </Drawer.Navigator>
  );
}
  • 嵌套时注意标题栏的归属:通常在叶子导航器中显示标题,父级导航器设置 headerShown: false,避免双重标题。
  • 可以跨导航器跳转,但需要明确目标路由的全路径,或使用 navigation.getParent() 获取父导航器。

参数传递与类型安全(TypeScript)

使用 TypeScript 可以获得完整的参数校验和自动补全。

type RootStackParamList = {
  Home: undefined;
  Details: { itemId: number };
};

const Stack = createNativeStackNavigator<RootStackParamList>();

此时 navigation.navigate('Details', { itemId: 123 }) 会强制你提供正确的参数。

常见问题与性能优化

  • 内存管理:React Navigation 默认保持栈内所有屏幕挂载,对于列表详情场景,可以使用 useIsFocused 钩子暂停非活跃屏幕的网络请求或动画。
  • 延迟加载:使用 React.lazy 配合 Suspense 实现屏幕代码分割,或利用 component 属性的动态 import 减少初始包大小。
  • 手势冲突:当嵌套多个可滑动的导航器(如 Drawer 嵌套在 Tab 中),需合理配置 gestureEnabledswipeEnabled 以避免误触。

总结与下一步

  • 栈导航:适合页面间的深度跳转,保留返回历史。
  • 标签导航:适合同级主功能的快速切换,通常置于应用底部。
  • 抽屉导航:适合侧边栏式全局菜单,承载低频但重要的入口。

掌握这三种导航器及其嵌套方式,你可以构建任意复杂度的 React Native 应用导航结构。建议查阅官方文档深入学习每个导航器的进阶配置,如透明模态、共享元素动画等。

现在尝试改造你的项目,为不同功能区域选择合适的导航模式,并组合它们来提升用户体验。