Skip to content

React Native 路由与导航

在 React Native 应用中,路由和导航是构建多页面应用的核心功能。本文将介绍如何使用 React Navigation 库来实现应用的导航功能。

React Navigation 简介

React Navigation 是 React Native 中最流行的导航库,它提供了多种导航器类型,适用于不同的应用场景:

  • StackNavigator - 用于屏幕之间的堆栈导航
  • TabNavigator - 用于底部或顶部的标签导航
  • DrawerNavigator - 用于侧边抽屉导航
  • SwitchNavigator - 用于认证流程等场景

安装 React Navigation

1. 安装核心依赖

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

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

2. 安装必要的依赖

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

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

3. 安装导航器

根据需要安装不同的导航器:

bash
# 安装 Stack 导航器
npm install @react-navigation/stack

# 安装 Tab 导航器
npm install @react-navigation/bottom-tabs

# 安装 Drawer 导航器
npm install @react-navigation/drawer

基本导航设置

1. 创建导航结构

首先,创建一个导航配置文件:

jsx
// App.js
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';

// 导入屏幕组件
import HomeScreen from './screens/HomeScreen';
import DetailScreen from './screens/DetailScreen';

const Stack = createStackNavigator();

export default function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName="Home">
        <Stack.Screen 
          name="Home" 
          component={HomeScreen} 
          options={{ title: '首页' }} 
        />
        <Stack.Screen 
          name="Detail" 
          component={DetailScreen} 
          options={{ title: '详情页' }} 
        />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

2. 屏幕组件

创建屏幕组件:

jsx
// screens/HomeScreen.js
import React from 'react';
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';

const HomeScreen = ({ navigation }) => {
  return (
    <View style={styles.container}>
      <Text style={styles.title}>首页</Text>
      <TouchableOpacity 
        style={styles.button} 
        onPress={() => navigation.navigate('Detail', { id: 1 })}>
        <Text style={styles.buttonText}>查看详情</Text>
      </TouchableOpacity>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 20,
  },
  button: {
    backgroundColor: '#007AFF',
    padding: 10,
    borderRadius: 5,
  },
  buttonText: {
    color: 'white',
    fontSize: 16,
  },
});

export default HomeScreen;
jsx
// screens/DetailScreen.js
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';

const DetailScreen = ({ route, navigation }) => {
  const { id } = route.params;
  
  return (
    <View style={styles.container}>
      <Text style={styles.title}>详情页</Text>
      <Text style={styles.info}>ID: {id}</Text>
    </View>
  );
};

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

export default DetailScreen;

导航类型

1. Stack 导航

Stack 导航是最基本的导航类型,用于屏幕之间的堆栈式导航:

jsx
import { createStackNavigator } from '@react-navigation/stack';

const Stack = createStackNavigator();

function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator
        initialRouteName="Home"
        screenOptions={{
          headerStyle: {
            backgroundColor: '#f4511e',
          },
          headerTintColor: '#fff',
          headerTitleStyle: {
            fontWeight: 'bold',
          },
        }}
      >
        <Stack.Screen 
          name="Home" 
          component={HomeScreen} 
          options={{ title: '首页' }} 
        />
        <Stack.Screen 
          name="Detail" 
          component={DetailScreen} 
          options={({ route }) => ({ title: route.params.name })} 
        />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

2. Tab 导航

Tab 导航用于底部或顶部的标签导航:

jsx
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { Ionicons } from '@expo/vector-icons';

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 === 'Settings') {
            iconName = focused ? 'settings' : 'settings-outline';
          }

          return <Ionicons name={iconName} size={size} color={color} />;
        },
        tabBarActiveTintColor: 'tomato',
        tabBarInactiveTintColor: 'gray',
      })}
    >
      <Tab.Screen name="Home" component={HomeScreen} options={{ title: '首页' }} />
      <Tab.Screen name="Settings" component={SettingsScreen} options={{ title: '设置' }} />
    </Tab.Navigator>
  );
}

3. Drawer 导航

Drawer 导航用于侧边抽屉导航:

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

const Drawer = createDrawerNavigator();

function DrawerNavigator() {
  return (
    <Drawer.Navigator initialRouteName="Home">
      <Drawer.Screen name="Home" component={HomeScreen} options={{ title: '首页' }} />
      <Drawer.Screen name="Settings" component={SettingsScreen} options={{ title: '设置' }} />
      <Drawer.Screen name="Profile" component={ProfileScreen} options={{ title: '个人中心' }} />
    </Drawer.Navigator>
  );
}

导航参数传递

1. 传递参数

jsx
// 从 HomeScreen 传递参数到 DetailScreen
navigation.navigate('Detail', {
  itemId: 86,
  otherParam: 'anything you want here',
});

2. 接收参数

jsx
// 在 DetailScreen 中接收参数
const DetailScreen = ({ route, navigation }) => {
  const { itemId, otherParam } = route.params;
  
  return (
    <View>
      <Text>Item ID: {itemId}</Text>
      <Text>Other Param: {otherParam}</Text>
    </View>
  );
};

3. 更新参数

jsx
// 更新路由参数
navigation.setParams({ 
  itemId: 99,
  otherParam: 'updated value',
});

导航选项

1. 自定义头部

jsx
// 静态头部选项
function HomeScreen({ navigation }) {
  return (
    <View>
      <Text>Home Screen</Text>
    </View>
  );
}

HomeScreen.navigationOptions = {
  title: '首页',
  headerStyle: {
    backgroundColor: '#f4511e',
  },
  headerTintColor: '#fff',
  headerTitleStyle: {
    fontWeight: 'bold',
  },
};

// 动态头部选项
function DetailScreen({ route }) {
  return (
    <View>
      <Text>Detail Screen</Text>
    </View>
  );
}

DetailScreen.navigationOptions = ({ route }) => ({
  title: route.params.name,
});

2. 隐藏头部

jsx
<Stack.Screen 
  name="Home" 
  component={HomeScreen} 
  options={{ headerShown: false }} 
/>

深层链接

1. 配置深层链接

jsx
const linking = {
  prefixes: ['myapp://', 'https://myapp.com'],
  config: {
    screens: {
      Home: 'home',
      Detail: 'detail/:id',
      Settings: 'settings',
    },
  },
};

function App() {
  return (
    <NavigationContainer linking={linking}>
      {/* 导航器 */}
    </NavigationContainer>
  );
}

2. 处理深层链接

当应用通过深层链接打开时,React Navigation 会自动导航到对应的屏幕,并将参数传递给该屏幕。

导航最佳实践

  1. 导航结构设计:根据应用的功能和用户流程设计合理的导航结构
  2. 参数传递:只传递必要的参数,避免传递大量数据
  3. 性能优化:使用 React.memo 优化屏幕组件,避免不必要的渲染
  4. 错误处理:处理导航过程中可能出现的错误
  5. 用户体验:添加适当的过渡动画,提供清晰的导航反馈
  6. 可访问性:确保导航元素对屏幕阅读器友好

总结

React Navigation 是 React Native 中实现导航功能的强大工具,它提供了多种导航器类型和丰富的配置选项,可以满足不同应用的需求。通过合理的导航设计和实现,可以为用户提供流畅、直观的应用体验。

基于 VitePress 的本地知识库