7-1 ~7-5 React Navigation v5

207 阅读3分钟

第一节:导航器基本介绍

什么是导航器?

在移动应用中,通常需要多个页面来实现复杂的功能。例如:

  • iOS 的设置应用采用堆栈式导航。
  • 照片应用使用底部标签导航。
  • Android 的联系人应用使用抽屉式导航。

导航器的作用是管理页面之间的跳转、传参、记录导航历史,并提供统一的标题栏等组件。React Navigation 是 React Native 官方推荐的导航解决方案。它完全基于 React Native 组件实现,具有高度的灵活性和定制能力,性能表现流畅。

React Navigation v5 是目前推荐的版本。与之前的版本相比,v5 将导航器拆分为独立的包,并采用组件化的方式实现,支持动态配置导航。这种设计更符合 React 的理念,也更易于使用。

第二节:安装 React Navigation

在本节中,我们将学习如何在项目中安装 React Navigation。

安装步骤

  1. 安装核心包和依赖项

    yarn add @react-navigation/native
    yarn add react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-view
    
    • react-native-reanimated:高性能动画库。
    • react-native-gesture-handler:跨平台手势处理库。
    • react-native-screens:用于优化性能的屏幕组件。
    • react-native-safe-area-context:提供安全区域支持,避免刘海屏等问题。
    • @react-native-community/masked-view:用于堆栈导航器的蒙版视图。
  2. 配置 Android 项目

    • 如果使用 React Native 0.60 及以上版本,自动链接功能会处理依赖项,无需手动运行 react-native link

    • 如果需要支持 iOS,运行以下命令:

      cd ios && pod install && cd ..
      
  3. 修改 Android 原生代码

    • android/app/build.gradledependencies 中添加:

      implementation 'androidx.appcompat:appcompat:1.1.0-rc01'
      implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0-alpha02'
      
    • 修改 android/app/src/main/java/MainActivity.java,支持手势系统:

      import com.facebook.react.ReactActivityDelegate;
      import com.facebook.react.ReactRootView;
      import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;
      
      @Override
      protected ReactActivityDelegate createReactActivityDelegate() {
        return new ReactActivityDelegate(this, getMainComponentName()) {
          @Override
          protected ReactRootView createRootView() {
            return new RNGestureHandlerEnabledRootView(MainActivity.this);
          }
        };
      }
      
  4. index.js 中添加

    import 'react-native-gesture-handler';
    

    如果不添加这一行,应用在生产环境中可能会闪退。

第三节:堆栈式导航器

堆栈式导航器的使用

  1. 安装堆栈式导航器

    yarn add @react-navigation/stack
    
  2. 创建页面组件

    pages 文件夹中创建 Home.tsxDetail.tsx,它们是普通的 React Native 组件。

  3. 配置导航器

    navigator/index.tsx 中创建导航器:

    import React from 'react';
    import { NavigationContainer } from '@react-navigation/native';
    import { createStackNavigator } from '@react-navigation/stack';
    
    export type RootStackParamList = {
      Home: undefined;
      Detail: undefined;
    };
    
    const Stack = createStackNavigator<RootStackParamList>();
    
    const Navigator = () => (
      <NavigationContainer>
        <Stack.Navigator>
          <Stack.Screen name="Home" component={Home} />
          <Stack.Screen name="Detail" component={Detail} />
        </Stack.Navigator>
      </NavigationContainer>
    );
    
    export default Navigator;
    
  4. 配置标题栏

    • 设置全局样式:

      <Stack.Navigator
        screenOptions={{
          headerTitleAlign: 'center',
          headerStyleInterpolator: HeaderStyleInterpolators.forUIKit,
          cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS,
          gestureEnabled: true,
          gestureDirection: 'horizontal',
          headerStyle: {
            ...Platform.select({
              android: {
                elevation: 0,
                borderBottomWidth: StyleSheet.hairlineWidth,
              },
            }),
          },
        }}
      >
      
    • 为页面设置标题:

      <Stack.Screen name="Home" component={Home} options={{ headerTitle: '首页' }} />
      <Stack.Screen name="Detail" component={Detail} options={{ headerTitle: '详情页' }} />
      
  5. 页面跳转与传参

    • Home 页面中:

      navigation.navigate('Detail', { id: 10 });
      
    • Detail 页面中接收参数:

      const { params } = route;
      console.log(params.id);
      

第四节:标签导航器

标签导航器的使用

  1. 安装标签导航器

    yarn add @react-navigation/bottom-tabs
    
  2. 创建标签导航器

    navigator/BottomTabs.tsx 中创建底部标签导航器:

    import React from 'react';
    import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
    
    export type BottomTabParamList = {
      Home: undefined;
      Listen: undefined;
      Found: undefined;
      Account: undefined;
    };
    
    const Tab = createBottomTabNavigator<BottomTabParamList>();
    
    const BottomTabs = () => (
      <Tab.Navigator tabBarOptions={{ activeTintColor: '#f86442' }}>
        <Tab.Screen name="Home" component={Home} options={{ tabBarLabel: '首页' }} />
        <Tab.Screen name="Listen" component={Listen} options={{ tabBarLabel: '我听' }} />
        <Tab.Screen name="Found" component={Found} options={{ tabBarLabel: '发现' }} />
        <Tab.Screen name="Account" component={Account} options={{ tabBarLabel: '我的' }} />
      </Tab.Navigator>
    );
    
    export default BottomTabs;
    
  3. 导航器嵌套

    • 在堆栈导航器中嵌套标签导航器:

      <Stack.Screen name="BottomTabs" component={BottomTabs} />
      
    • 在标签导航器中嵌套堆栈导航器:

      <Tab.Screen name="Stack" component={Stack} />
      
  4. 动态修改标题栏

    使用 route.state 动态获取当前页面的标题:

    function getHeaderTitle(route) {
      const routeName = route.state
        ? route.state.routes[route.state.index].name
        : route.params?.screen || 'Home';
    
      switch (routeName) {
        case 'Home':
          return '首页';
        case 'Listen':
          return '我听';
        case 'Found':
          return '发现';
        case 'Account':
          return '我的';
      }
    }
    
    navigation.setOptions({
      headerTitle: getHeaderTitle(route),
    });