React Navigation基础 #

概述 #

React Navigation 是 React Native 社区最流行的导航解决方案。它提供了多种导航器类型,可以满足各种应用场景的导航需求。

安装 #

安装核心包 #

bash
npm install @react-navigation/native

安装依赖 #

bash
npm install react-native-screens react-native-safe-area-context

安装导航器 #

bash
npm install @react-navigation/native-stack
npm install @react-navigation/bottom-tabs
npm install @react-navigation/drawer

iOS 配置 #

bash
cd ios && pod install

基本配置 #

在应用根组件包裹 NavigationContainer:

tsx
import React from 'react';
import {NavigationContainer} from '@react-navigation/native';
import {createNativeStackNavigator} from '@react-navigation/native-stack';
import HomeScreen from './screens/HomeScreen';
import DetailsScreen from './screens/DetailsScreen';

const Stack = createNativeStackNavigator();

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

export default App;

Stack 导航 #

Stack 导航是最常用的导航方式,页面以堆栈形式管理。

基本使用 #

tsx
import React from 'react';
import {View, Text, Button, StyleSheet} from 'react-native';
import {NativeStackScreenProps} from '@react-navigation/native-stack';

type RootStackParamList = {
  Home: undefined;
  Details: {itemId: string; title: string};
  Profile: {userId: string};
};

type Props = NativeStackScreenProps<RootStackParamList, 'Home'>;

const HomeScreen: React.FC<Props> = ({navigation}) => {
  return (
    <View style={styles.container}>
      <Text style={styles.title}>Home Screen</Text>
      <Button
        title="Go to Details"
        onPress={() => navigation.navigate('Details', {itemId: '42', title: 'My Item'})}
      />
    </View>
  );
};

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

export default HomeScreen;

接收参数 #

tsx
import React from 'react';
import {View, Text, Button, StyleSheet} from 'react-native';
import {NativeStackScreenProps} from '@react-navigation/native-stack';

type RootStackParamList = {
  Details: {itemId: string; title: string};
};

type Props = NativeStackScreenProps<RootStackParamList, 'Details'>;

const DetailsScreen: React.FC<Props> = ({route, navigation}) => {
  const {itemId, title} = route.params;

  return (
    <View style={styles.container}>
      <Text style={styles.title}>{title}</Text>
      <Text>Item ID: {itemId}</Text>
      <Button title="Go back" onPress={() => navigation.goBack()} />
    </View>
  );
};

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

export default DetailsScreen;

导航方法 #

tsx
const NavigationMethods = ({navigation}) => {
  return (
    <View>
      {}
      <Button title="Navigate" onPress={() => navigation.navigate('Details')} />

      {}
      <Button title="Push" onPress={() => navigation.push('Details')} />

      {}
      <Button title="Go Back" onPress={() => navigation.goBack()} />

      {}
      <Button title="Pop to Top" onPress={() => navigation.popToTop()} />

      {}
      <Button title="Replace" onPress={() => navigation.replace('Details')} />

      {}
      <Button
        title="Reset"
        onPress={() =>
          navigation.reset({
            index: 0,
            routes: [{name: 'Home'}],
          })
        }
      />
    </View>
  );
};

配置标题栏 #

tsx
const Stack = createNativeStackNavigator();

const App = () => {
  return (
    <NavigationContainer>
      <Stack.Navigator
        initialRouteName="Home"
        screenOptions={{
          headerStyle: {
            backgroundColor: '#007AFF',
          },
          headerTintColor: '#fff',
          headerTitleStyle: {
            fontWeight: 'bold',
          },
        }}>
        <Stack.Screen
          name="Home"
          component={HomeScreen}
          options={{
            title: '首页',
            headerRight: () => (
              <Button onPress={() => console.log('Info')} title="Info" color="#fff" />
            ),
          }}
        />
        <Stack.Screen
          name="Details"
          component={DetailsScreen}
          options={({route}) => ({title: route.params.title})}
        />
      </Stack.Navigator>
    </NavigationContainer>
  );
};

动态设置标题 #

tsx
import React, {useLayoutEffect} from 'react';
import {View, Text, Button} from 'react-native';

const DetailsScreen = ({navigation, route}) => {
  const {title} = route.params;

  useLayoutEffect(() => {
    navigation.setOptions({
      title: title,
      headerRight: () => (
        <Button title="Share" onPress={() => console.log('Share')} />
      ),
    });
  }, [navigation, title]);

  return (
    <View>
      <Text>Details Screen</Text>
    </View>
  );
};

Tab 导航 #

Tab 导航用于底部标签栏导航。

基本使用 #

tsx
import React from 'react';
import {View, Text, StyleSheet} from 'react-native';
import {NavigationContainer} from '@react-navigation/native';
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
import Icon from 'react-native-vector-icons/Ionicons';

const Tab = createBottomTabNavigator();

const HomeScreen = () => (
  <View style={styles.container}>
    <Text>Home Screen</Text>
  </View>
);

const SettingsScreen = () => (
  <View style={styles.container}>
    <Text>Settings Screen</Text>
  </View>
);

const App = () => {
  return (
    <NavigationContainer>
      <Tab.Navigator
        screenOptions={({route}) => ({
          tabBarIcon: ({focused, color, size}) => {
            let iconName: string;

            if (route.name === 'Home') {
              iconName = focused ? 'home' : 'home-outline';
            } else if (route.name === 'Settings') {
              iconName = focused ? 'settings' : 'settings-outline';
            }

            return <Icon name={iconName} size={size} color={color} />;
          },
          tabBarActiveTintColor: '#007AFF',
          tabBarInactiveTintColor: 'gray',
        })}>
        <Tab.Screen name="Home" component={HomeScreen} />
        <Tab.Screen name="Settings" component={SettingsScreen} />
      </Tab.Navigator>
    </NavigationContainer>
  );
};

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

export default App;

Tab 配置选项 #

tsx
<Tab.Navigator
  screenOptions={{
    tabBarActiveTintColor: '#007AFF',
    tabBarInactiveTintColor: '#999',
    tabBarStyle: {
      backgroundColor: '#fff',
      borderTopWidth: 1,
      borderTopColor: '#eee',
    },
    tabBarLabelStyle: {
      fontSize: 12,
      fontWeight: '600',
    },
  }}>
  <Tab.Screen
    name="Home"
    component={HomeScreen}
    options={{
      tabBarLabel: '首页',
      tabBarBadge: 3,
    }}
  />
  <Tab.Screen
    name="Profile"
    component={ProfileScreen}
    options={{
      tabBarLabel: '我的',
    }}
  />
</Tab.Navigator>

Drawer 导航 #

Drawer 导航用于侧边抽屉菜单。

基本使用 #

tsx
import React from 'react';
import {View, Text, Button, StyleSheet} from 'react-native';
import {NavigationContainer} from '@react-navigation/native';
import {createDrawerNavigator} from '@react-navigation/drawer';

const Drawer = createDrawerNavigator();

const HomeScreen = ({navigation}) => (
  <View style={styles.container}>
    <Text>Home Screen</Text>
    <Button title="Open Drawer" onPress={() => navigation.openDrawer()} />
  </View>
);

const NotificationsScreen = () => (
  <View style={styles.container}>
    <Text>Notifications Screen</Text>
  </View>
);

const App = () => {
  return (
    <NavigationContainer>
      <Drawer.Navigator
        initialRouteName="Home"
        screenOptions={{
          drawerStyle: {
            backgroundColor: '#fff',
            width: 240,
          },
          drawerActiveTintColor: '#007AFF',
        }}>
        <Drawer.Screen name="Home" component={HomeScreen} />
        <Drawer.Screen name="Notifications" component={NotificationsScreen} />
      </Drawer.Navigator>
    </NavigationContainer>
  );
};

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

export default App;

自定义抽屉内容 #

tsx
import React from 'react';
import {View, Text, TouchableOpacity, StyleSheet} from 'react-native';
import {DrawerContentScrollView, DrawerItem} from '@react-navigation/drawer';

const CustomDrawerContent = (props) => {
  return (
    <DrawerContentScrollView {...props}>
      <View style={styles.header}>
        <Text style={styles.userName}>John Doe</Text>
        <Text style={styles.email}>john@example.com</Text>
      </View>
      
      <DrawerItem
        label="Home"
        onPress={() => props.navigation.navigate('Home')}
      />
      <DrawerItem
        label="Profile"
        onPress={() => props.navigation.navigate('Profile')}
      />
      <DrawerItem
        label="Settings"
        onPress={() => props.navigation.navigate('Settings')}
      />
      
      <View style={styles.footer}>
        <DrawerItem
          label="Logout"
          onPress={() => console.log('Logout')}
        />
      </View>
    </DrawerContentScrollView>
  );
};

const styles = StyleSheet.create({
  header: {
    padding: 20,
    borderBottomWidth: 1,
    borderBottomColor: '#eee',
  },
  userName: {
    fontSize: 18,
    fontWeight: 'bold',
  },
  email: {
    fontSize: 14,
    color: '#666',
    marginTop: 4,
  },
  footer: {
    marginTop: 'auto',
    borderTopWidth: 1,
    borderTopColor: '#eee',
  },
});

组合导航 #

将多种导航器组合使用:

tsx
import React from 'react';
import {NavigationContainer} from '@react-navigation/native';
import {createNativeStackNavigator} from '@react-navigation/native-stack';
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';

const Stack = createNativeStackNavigator();
const Tab = createBottomTabNavigator();

const HomeStack = () => (
  <Stack.Navigator>
    <Stack.Screen name="HomeList" component={HomeListScreen} />
    <Stack.Screen name="HomeDetail" component={HomeDetailScreen} />
  </Stack.Navigator>
);

const ProfileStack = () => (
  <Stack.Navigator>
    <Stack.Screen name="ProfileMain" component={ProfileScreen} />
    <Stack.Screen name="EditProfile" component={EditProfileScreen} />
  </Stack.Navigator>
);

const App = () => {
  return (
    <NavigationContainer>
      <Tab.Navigator>
        <Tab.Screen
          name="HomeTab"
          component={HomeStack}
          options={{headerShown: false, tabBarLabel: '首页'}}
        />
        <Tab.Screen
          name="ProfileTab"
          component={ProfileStack}
          options={{headerShown: false, tabBarLabel: '我的'}}
        />
      </Tab.Navigator>
    </NavigationContainer>
  );
};

导航状态管理 #

useNavigation Hook #

tsx
import React from 'react';
import {Button} from 'react-native';
import {useNavigation} from '@react-navigation/native';

const MyComponent = () => {
  const navigation = useNavigation();

  return (
    <Button
      title="Go to Details"
      onPress={() => navigation.navigate('Details')}
    />
  );
};

useRoute Hook #

tsx
import React from 'react';
import {Text} from 'react-native';
import {useRoute} from '@react-navigation/native';

const MyComponent = () => {
  const route = useRoute();
  const {itemId} = route.params;

  return <Text>Item ID: {itemId}</Text>;
};

useFocusEffect #

页面获得焦点时执行:

tsx
import React from 'react';
import {useFocusEffect} from '@react-navigation/native';

const ProfileScreen = () => {
  useFocusEffect(
    React.useCallback(() => {
      console.log('Screen focused');
      return () => {
        console.log('Screen unfocused');
      };
    }, []),
  );

  return <Text>Profile Screen</Text>;
};

总结 #

React Navigation 是 React Native 的标准导航解决方案:

  • Stack 导航:页面堆栈管理
  • Tab 导航:底部标签栏
  • Drawer 导航:侧边抽屉菜单
  • 组合导航:多种导航器组合使用

掌握这些导航方式,可以构建复杂的应用导航结构。

继续学习 导航进阶,了解导航参数传递、深层链接等高级功能。

最后更新:2026-03-28