Skip to content

React Native 导航与路由

React Navigation 6.x

基础配置

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

// 类型定义
type RootStackParamList = {
  Home: undefined;
  Profile: { userId: string };
  Settings: { section?: string };
};

const Stack = createNativeStackNavigator<RootStackParamList>();

function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName="Home">
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen 
          name="Profile" 
          component={ProfileScreen}
          options={{ title: '个人资料' }}
        />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

导航器类型

tsx
// 1. Stack Navigator - 堆栈导航
import { createNativeStackNavigator } from '@react-navigation/native-stack';

// 2. Tab Navigator - 底部标签
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';

// 3. Drawer Navigator - 抽屉导航
import { createDrawerNavigator } from '@react-navigation/drawer';

// 4. 嵌套导航
function App() {
  return (
    <NavigationContainer>
      <Drawer.Navigator>
        <Drawer.Screen name="MainTabs" component={TabNavigator} />
        <Drawer.Screen name="Settings" component={SettingsStack} />
      </Drawer.Navigator>
    </NavigationContainer>
  );
}

导航操作

tsx
import { useNavigation, useRoute } from '@react-navigation/native';
import type { NativeStackNavigationProp } from '@react-navigation/native-stack';

type NavigationProp = NativeStackNavigationProp<RootStackParamList>;

function HomeScreen() {
  const navigation = useNavigation<NavigationProp>();
  
  return (
    <View>
      {/* 基础导航 */}
      <Button onPress={() => navigation.navigate('Profile', { userId: '123' })} />
      
      {/* 替换当前页面 */}
      <Button onPress={() => navigation.replace('Settings')} />
      
      {/* 返回 */}
      <Button onPress={() => navigation.goBack()} />
      
      {/* 返回到栈顶 */}
      <Button onPress={() => navigation.popToTop()} />
      
      {/* 重置导航状态 */}
      <Button onPress={() => navigation.reset({
        index: 0,
        routes: [{ name: 'Home' }],
      })} />
    </View>
  );
}

深度链接 (Deep Linking)

配置 Linking

tsx
const linking = {
  prefixes: ['myapp://', 'https://myapp.com'],
  config: {
    screens: {
      Home: '',
      Profile: 'user/:userId',
      Settings: {
        path: 'settings/:section?',
        parse: {
          section: (section: string) => section.toLowerCase(),
        },
      },
      NotFound: '*',
    },
  },
};

function App() {
  return (
    <NavigationContainer 
      linking={linking}
      fallback={<LoadingScreen />}
    >
      <Stack.Navigator>
        {/* screens */}
      </Stack.Navigator>
    </NavigationContainer>
  );
}

原生配置

xml
<!-- Android: AndroidManifest.xml -->
<intent-filter>
  <action android:name="android.intent.action.VIEW" />
  <category android:name="android.intent.category.DEFAULT" />
  <category android:name="android.intent.category.BROWSABLE" />
  <data android:scheme="myapp" />
  <data android:scheme="https" android:host="myapp.com" />
</intent-filter>
swift
// iOS: AppDelegate.swift
func application(_ app: UIApplication, open url: URL, options: ...) -> Bool {
  return RCTLinkingManager.application(app, open: url, options: options)
}

导航状态持久化

tsx
import AsyncStorage from '@react-native-async-storage/async-storage';

function App() {
  const [isReady, setIsReady] = useState(false);
  const [initialState, setInitialState] = useState();

  useEffect(() => {
    const restoreState = async () => {
      const savedState = await AsyncStorage.getItem('NAVIGATION_STATE');
      if (savedState) {
        setInitialState(JSON.parse(savedState));
      }
      setIsReady(true);
    };
    restoreState();
  }, []);

  if (!isReady) return <SplashScreen />;

  return (
    <NavigationContainer
      initialState={initialState}
      onStateChange={(state) =>
        AsyncStorage.setItem('NAVIGATION_STATE', JSON.stringify(state))
      }
    >
      {/* ... */}
    </NavigationContainer>
  );
}

面试要点

  1. 导航器选择:Stack/Tab/Drawer 适用场景
  2. 类型安全:ParamList 类型定义
  3. 深度链接:URL 解析与原生配置
  4. 状态管理:导航状态持久化与恢复

前端面试知识库