expo-router
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseExpo Router Patterns
Expo Router 实践模式
Stack Navigator Configuration
Stack 导航器配置
Root Layout Setup
根布局设置
Use on the Stack component to set defaults for all screens. Do NOT explicitly list every screen - routes are auto-discovered from the file structure.
screenOptionstsx
// app/_layout.tsx
import { Stack } from 'expo-router';
export default function RootLayout() {
return (
<Stack screenOptions={{ headerShown: false }} />
);
}在Stack组件上使用为所有屏幕设置默认配置。无需显式列出每个屏幕——路由会从文件结构中自动识别。
screenOptionstsx
// app/_layout.tsx
import { Stack } from 'expo-router';
export default function RootLayout() {
return (
<Stack screenOptions={{ headerShown: false }} />
);
}Per-Screen Configuration
单屏幕配置
Individual screens configure their own options using within the component file:
<Stack.Screen>tsx
// app/lesson/[id].tsx
import { Stack } from 'expo-router';
export default function LessonScreen() {
return (
<View>
<Stack.Screen
options={{
title: 'Lesson',
headerShown: true,
headerBackTitle: 'Back',
}}
/>
{/* Screen content */}
</View>
);
}单个屏幕可在组件文件内通过配置自身选项:
<Stack.Screen>tsx
// app/lesson/[id].tsx
import { Stack } from 'expo-router';
export default function LessonScreen() {
return (
<View>
<Stack.Screen
options={{
title: 'Lesson',
headerShown: true,
headerBackTitle: 'Back',
}}
/>
{/* 屏幕内容 */}
</View>
);
}Dynamic Header Configuration
动态头部配置
Use with for dynamic header content like buttons:
useNavigationsetOptionstsx
import { useNavigation } from 'expo-router';
import { useLayoutEffect } from 'react';
export default function Screen() {
const navigation = useNavigation();
useLayoutEffect(() => {
navigation.setOptions({
headerRight: () => (
<Pressable onPress={handlePress}>
<Ionicons name="add" size={28} />
</Pressable>
),
});
}, [navigation]);
return <View>{/* content */}</View>;
}结合与实现动态头部内容,比如添加按钮:
useNavigationsetOptionstsx
import { useNavigation } from 'expo-router';
import { useLayoutEffect } from 'react';
export default function Screen() {
const navigation = useNavigation();
useLayoutEffect(() => {
navigation.setOptions({
headerRight: () => (
<Pressable onPress={handlePress}>
<Ionicons name="add" size={28} />
</Pressable>
),
});
}, [navigation]);
return <View>{/* 内容 */}</View>;
}Native Tabs (expo-router/unstable-native-tabs
)
expo-router/unstable-native-tabs原生标签页(expo-router/unstable-native-tabs
)
expo-router/unstable-native-tabsNative tabs provide platform-native tab bar with SF Symbols on iOS:
tsx
// app/(tabs)/_layout.tsx
import { Icon, Label, NativeTabs } from 'expo-router/unstable-native-tabs';
export default function TabLayout() {
return (
<NativeTabs>
<NativeTabs.Trigger name="index" options={{ title: 'Home' }}>
<Icon sf="house.fill" drawable="custom_android_drawable" />
<Label>Home</Label>
</NativeTabs.Trigger>
</NativeTabs>
);
}原生标签页提供平台原生的标签栏,在iOS上支持SF Symbols:
tsx
// app/(tabs)/_layout.tsx
import { Icon, Label, NativeTabs } from 'expo-router/unstable-native-tabs';
export default function TabLayout() {
return (
<NativeTabs>
<NativeTabs.Trigger name="index" options={{ title: 'Home' }}>
<Icon sf="house.fill" drawable="custom_android_drawable" />
<Label>Home</Label>
</NativeTabs.Trigger>
</NativeTabs>
);
}Key Principles
核心原则
- File-based routing: Routes are auto-discovered from the directory structure
app/ - Minimal configuration: Only configure what you need to override
- Screen-level options: Screens configure their own headers/options using within the component
<Stack.Screen> - Layout files: files define navigation structure for their directory
_layout.tsx - Route groups: Parentheses like create route groups without affecting the URL path
(tabs)
- 基于文件的路由:路由从目录结构中自动识别
app/ - 最小化配置:仅配置需要覆盖的内容
- 屏幕级选项:屏幕通过组件内的配置自身的头部/选项
<Stack.Screen> - 布局文件:文件为其所在目录定义导航结构
_layout.tsx - 路由分组:使用括号如创建路由分组,不会影响URL路径
(tabs)
Common Mistakes to Avoid
需避免的常见错误
- Don't list every screen explicitly in Stack - they're auto-discovered
- Don't use for route-specific settings - use
screenOptionsin the route file<Stack.Screen> - Don't nest navigators deeply - use file-based routing for cleaner structure
- 不要在Stack中显式列出每个屏幕——它们会被自动识别
- 不要使用配置路由特定设置——应在路由文件中使用
screenOptions<Stack.Screen> - 不要过度嵌套导航器——使用基于文件的路由实现更清晰的结构