Skip to content

React Navigation 安装与配置

第五部分:路由导航(页面跳转)

React Navigation 是 React Native 中最流行的导航库,用于实现页面之间的跳转和导航。本文将详细介绍 React Navigation 的安装和基本配置。

1. 安装 React Navigation

安装核心依赖

首先,需要安装 React Navigation 的核心依赖包:

bash
# 使用 npm
npm install @react-navigation/native

# 使用 yarn
yarn add @react-navigation/native

安装必要的依赖

React Navigation 需要一些额外的依赖来正常工作:

bash
# 使用 npm
npm install react-native-screens react-native-safe-area-context

# 使用 yarn
yarn add react-native-screens react-native-safe-area-context

安装导航器

根据需要选择安装不同类型的导航器:

1. 栈导航器(Stack Navigator)

bash
# 使用 npm
npm install @react-navigation/stack

# 使用 yarn
yarn add @react-navigation/stack

2. 标签导航器(Tab Navigator)

bash
# 使用 npm
npm install @react-navigation/bottom-tabs

# 使用 yarn
yarn add @react-navigation/bottom-tabs

3. 抽屉导航器(Drawer Navigator)

bash
# 使用 npm
npm install @react-navigation/drawer

# 使用 yarn
yarn add @react-navigation/drawer

安装手势处理器

对于使用抽屉导航器或需要手势支持的应用,需要安装手势处理器:

bash
# 使用 npm
npm install react-native-gesture-handler

# 使用 yarn
yarn add react-native-gesture-handler

2. 基本配置

1. 配置入口文件

在应用的入口文件(通常是 App.jsindex.js)中,需要配置 React Navigation:

jsx
import 'react-native-gesture-handler'; // 必须在第一行导入
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import HomeScreen from './screens/HomeScreen';
import DetailsScreen from './screens/DetailsScreen';

const Stack = createStackNavigator();

export default function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Details" component={DetailsScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

2. 配置屏幕组件

创建 screens 目录并添加屏幕组件:

HomeScreen.js

jsx
import React from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';

export default function HomeScreen({ navigation }) {
  return (
    <View style={styles.container}>
      <Text style={styles.title}>首页</Text>
      <Button
        title="跳转到详情页"
        onPress={() => navigation.navigate('Details')}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  title: {
    fontSize: 24,
    marginBottom: 20,
  },
});

DetailsScreen.js

jsx
import React from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';

export default function DetailsScreen({ navigation }) {
  return (
    <View style={styles.container}>
      <Text style={styles.title}>详情页</Text>
      <Button
        title="返回首页"
        onPress={() => navigation.goBack()}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  title: {
    fontSize: 24,
    marginBottom: 20,
  },
});

3. 平台特定配置

Android 配置

在 Android 上,需要在 android/app/src/main/java/com/yourprojectname/MainActivity.java 文件中添加以下配置:

java
package com.yourprojectname;

import com.facebook.react.ReactActivity;
import com.facebook.react.ReactActivityDelegate;
import com.facebook.react.ReactRootView;
import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView;

public class MainActivity extends ReactActivity {

  /**
   * Returns the name of the main component registered from JavaScript.
   * This is used to schedule rendering of the component.
   */
  @Override
  protected String getMainComponentName() {
    return "YourProjectName";
  }

  @Override
  protected ReactActivityDelegate createReactActivityDelegate() {
    return new ReactActivityDelegate(this, getMainComponentName()) {
      @Override
      protected ReactRootView createRootView() {
        return new RNGestureHandlerEnabledRootView(MainActivity.this);
      }
    };
  }
}

iOS 配置

在 iOS 上,通常不需要额外的配置。如果遇到问题,可以尝试执行以下命令:

bash
npx pod-install

4. 导航容器配置

自定义主题

可以为导航容器配置自定义主题:

jsx
import React from 'react';
import { NavigationContainer, DefaultTheme } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import HomeScreen from './screens/HomeScreen';
import DetailsScreen from './screens/DetailsScreen';

const Stack = createStackNavigator();

// 自定义主题
const MyTheme = {
  ...DefaultTheme,
  colors: {
    ...DefaultTheme.colors,
    primary: '#4CAF50',
    background: '#f5f5f5',
    card: '#ffffff',
    text: '#333333',
    border: '#dddddd',
  },
};

export default function App() {
  return (
    <NavigationContainer theme={MyTheme}>
      <Stack.Navigator>
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Details" component={DetailsScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

导航状态持久化

可以使用 @react-navigation/native 提供的 useLinking 钩子来实现导航状态的持久化:

jsx
import React from 'react';
import { NavigationContainer, useLinking } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import HomeScreen from './screens/HomeScreen';
import DetailsScreen from './screens/DetailsScreen';

const Stack = createStackNavigator();

function App() {
  const { getInitialState } = useLinking({
    prefixes: ['myapp://', 'https://myapp.com'],
    config: {
      screens: {
        Home: 'home',
        Details: 'details/:id',
      },
    },
  });

  const [isReady, setIsReady] = React.useState(false);
  const [initialState, setInitialState] = React.useState(null);

  React.useEffect(() => {
    const prepare = async () => {
      try {
        const state = await getInitialState();
        setInitialState(state);
      } catch (e) {
        console.error(e);
      } finally {
        setIsReady(true);
      }
    };

    prepare();
  }, [getInitialState]);

  if (!isReady) {
    return null; // 或者返回一个加载指示器
  }

  return (
    <NavigationContainer initialState={initialState}>
      <Stack.Navigator>
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Details" component={DetailsScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

export default App;

5. 常见问题与解决方案

问题 1:导航器不显示

问题:导航器安装后不显示或崩溃。

解决方案

  • 确保正确安装了所有必要的依赖
  • 确保在入口文件的第一行导入了 react-native-gesture-handler
  • 检查 Android 配置是否正确
  • 尝试重新构建应用:npx react-native run-androidnpx react-native run-ios

问题 2:手势不工作

问题:抽屉导航或其他手势不工作。

解决方案

  • 确保安装了 react-native-gesture-handler
  • 确保 Android 配置正确
  • 尝试使用 gestureEnabled 属性启用手势

问题 3:导航参数传递失败

问题:无法在屏幕之间传递参数。

解决方案

  • 确保使用正确的导航方法:navigation.navigate('ScreenName', { params })
  • 确保在目标屏幕中正确获取参数:const { route } = props; const { params } = route;

问题 4:导航栏样式修改失败

问题:无法修改导航栏的样式。

解决方案

  • 使用 screenOptions 属性设置导航栏样式
  • 使用 headerStyleheaderTintColorheaderTitleStyle 等属性
  • 对于自定义导航栏,可以使用 header 属性

6. 最佳实践

1. 组织导航结构

将导航相关的代码组织到单独的文件中,例如 navigation/index.js

jsx
// navigation/index.js
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import HomeScreen from '../screens/HomeScreen';
import DetailsScreen from '../screens/DetailsScreen';

const Stack = createStackNavigator();

export default function AppNavigation() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Details" component={DetailsScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

2. 使用类型定义

为导航参数添加类型定义,提高代码的可维护性:

typescript
// navigation/types.ts
export type RootStackParamList = {
  Home: undefined;
  Details: { id: number; title: string };
};

// 使用类型
export default function HomeScreen({
  navigation,
}: NativeStackScreenProps<RootStackParamList, 'Home'>) {
  return (
    <View>
      <Button
        title="跳转到详情页"
        onPress={() => navigation.navigate('Details', { id: 1, title: '详情' })}
      />
    </View>
  );
}

3. 合理使用导航选项

为不同的屏幕设置合适的导航选项:

jsx
<Stack.Navigator
  screenOptions={{
    headerStyle: {
      backgroundColor: '#4CAF50',
    },
    headerTintColor: '#fff',
    headerTitleStyle: {
      fontWeight: 'bold',
    },
  }}
>
  <Stack.Screen 
    name="Home" 
    component={HomeScreen}
    options={{
      title: '首页',
    }}
  />
  <Stack.Screen 
    name="Details" 
    component={DetailsScreen}
    options={({ route }) => ({
      title: route.params?.title || '详情页',
    })}
  />
</Stack.Navigator>

4. 处理深链接

配置深链接,让用户可以通过 URL 直接打开应用的特定页面:

jsx
const { getInitialState } = useLinking({
  prefixes: ['myapp://', 'https://myapp.com'],
  config: {
    screens: {
      Home: '',
      Details: 'details/:id',
    },
  },
});

7. 总结

React Navigation 是 React Native 中实现页面导航的强大工具。通过本文的学习,你应该掌握了以下内容:

  1. React Navigation 的安装和配置
  2. 基本导航结构的设置
  3. 平台特定的配置
  4. 导航容器的高级配置
  5. 常见问题的解决方案
  6. 最佳实践

在实际开发中,合理使用 React Navigation,可以创建出具有良好用户体验的导航流程,使应用更加专业和易用。

© 2026 编程马·菜鸟教程 版权所有