添加导航
编辑页面
在本章中,学习如何向 Expo 应用添加导航。
For the complete documentation index, see llms.txt. Use this Use this file to discover all available pages.
在本章中,我们将学习 Expo Router 的基础知识,创建堆栈导航和一个包含两个标签页的底部标签栏。

使用 Expo Router 设置基于文件的路由,在屏幕之间创建堆栈导航,并构建一个底部标签栏。
Expo Router 基础
Expo Router 是一个面向 React Native 和 Web 应用的基于文件的路由框架。它负责管理屏幕之间的导航,并在多个平台上使用相同的组件。要开始使用,我们需要了解以下约定:
- app 目录:一个特殊目录,只包含路由及其布局。添加到该目录中的任何文件都会成为原生应用中的一个屏幕,以及 Web 上的一个页面。
- 根布局:app/_layout.tsx 文件。它定义了共享 UI 元素,例如标题和标签栏,从而使不同路由之间保持一致。
- 文件名约定:像 index.tsx 这样的 Index 文件名会与其父目录匹配,不会新增路径段。例如,app 目录中的 index.tsx 文件匹配
/路由。 - 一个 route 文件会将 React 组件作为默认导出。它可以使用
.js、.jsx、.ts或.tsx扩展名。 - Android、iOS 和 web 共享统一的导航结构。
以上列表已经足够我们开始使用。有关完整功能列表,请参阅 Expo Router 简介。
1
向堆栈中添加新屏幕
让我们在 app 目录中创建一个名为 about.tsx 的新文件。当用户导航到 /about 路由时,它会显示该屏幕的名称。
import { Text, View, StyleSheet } from 'react-native'; export default function AboutScreen() { return ( <View style={styles.container}> <Text style={styles.text}>关于页面</Text> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#25292e', justifyContent: 'center', alignItems: 'center', }, text: { color: '#fff', }, });
在 app/_layout.tsx 中:
- 添加一个
<Stack.Screen />组件和一个options属性,以更新/about路由的标题。 - 通过添加
options属性,将/index路由的标题更新为Home。
import { Stack } from 'expo-router'; export default function RootLayout() { return ( <Stack> <Stack.Screen name="index" options={{ title: 'Home' }} /> <Stack.Screen name="about" options={{ title: 'About' }} /> </Stack> ); }
2
在屏幕之间导航
我们将使用 Expo Router 的 Link 组件从 /index 路由导航到 /about 路由。它是一个 React 组件,会根据给定的 href 属性渲染一个 <Text>。
- 在 index.tsx 中从
expo-router导入Link组件。 - 在
<Text>组件后添加一个Link组件,并传入指向/about路由的href属性。 - 为
Link组件添加fontSize、textDecorationLine和color样式。它接受与<Text>组件相同的属性。
import { Text, View, StyleSheet } from 'react-native'; import { Link } from 'expo-router'; export default function Index() { return ( <View style={styles.container}> <Text style={styles.text}>主页</Text> <Link href="/about" style={styles.button}> 前往关于页面 </Link> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#25292e', alignItems: 'center', justifyContent: 'center', }, text: { color: '#fff', }, button: { fontSize: 20, textDecorationLine: 'underline', color: '#fff', }, });
让我们看看应用中的变化。点击 Link 即可导航到 /about 路由:
3
添加一个找不到页面路由
当路由不存在时,我们可以使用 +not-found 路由来显示一个回退屏幕。这在我们希望在移动端导航到无效路由时显示自定义屏幕,而不是让应用崩溃,或者在 Web 上显示 404 错误时非常有用。Expo Router 使用一个特殊的 +not-found.tsx 文件来处理这种情况。
- 在 app 目录中创建一个名为 +not-found.tsx 的新文件,以添加
NotFoundScreen组件。 - 从
Stack.Screen添加options属性,为该路由显示自定义屏幕标题。 - 添加一个
Link组件,用于导航到/路由,它是我们的回退路由。
import { View, StyleSheet } from 'react-native'; import { Link, Stack } from 'expo-router'; export default function NotFoundScreen() { return ( <> <Stack.Screen options={{ title: 'Oops! Not Found' }} /> <View style={styles.container}> <Link href="/" style={styles.button}> 返回主页! </Link> </View> </> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#25292e', justifyContent: 'center', alignItems: 'center', }, button: { fontSize: 20, textDecorationLine: 'underline', color: '#fff', }, });
要测试这一点,请在 Web 浏览器中访问 http:localhost:8081/123 URL,因为在那里更容易更改 URL 路径。应用应该会显示 NotFoundScreen 组件:
4
添加底部标签导航器
此时,我们 app 目录的文件结构如下所示:
app_layout.tsx根布局index.tsx匹配路由 '/'about.tsx匹配路由 '/about'+not-found.tsx匹配任意 404 路由我们将为应用添加一个底部标签导航器,并复用现有的 Home 和 About 屏幕来创建一个标签布局(这是许多社交媒体应用中常见的导航模式,例如 X 或 BlueSky)。我们还会在根布局中继续使用堆栈导航器,这样 +not-found 路由就会显示在任何其他嵌套导航器之上。
- 在 app 目录中,添加一个 (tabs) 子目录。这个特殊目录用于将路由分组并在底部标签栏中显示它们。
- 在该目录中创建一个 (tabs)/_layout.tsx 文件。它将用于定义标签布局,且独立于根布局。
- 将现有的 index.tsx 和 about.tsx 文件移动到 (tabs) 目录中。app 目录结构将如下所示:
app_layout.tsx根布局+not-found.tsx匹配任意 404 路由(tabs)_layout.tsx标签布局index.tsx匹配路由 '/'about.tsx匹配路由 '/about'更新根布局文件,添加一个 (tabs) 路由:
import { Stack } from 'expo-router'; export default function RootLayout() { return ( <Stack> <Stack.Screen name="(tabs)" options={{ headerShown: false }} /> </Stack> ); }
在 (tabs)/_layout.tsx 中,添加一个 Tabs 组件来定义底部标签布局:
import { Tabs } from 'expo-router'; export default function TabLayout() { return ( <Tabs> <Tabs.Screen name="index" options={{ title: 'Home' }} /> <Tabs.Screen name="about" options={{ title: 'About' }} /> </Tabs> ); }
让我们现在看看应用,看看新的底部标签:
5
更新底部标签导航器的外观
现在,底部标签导航器在所有平台上的外观都相同,但并不符合我们应用的风格。例如,标签栏或标题没有显示自定义图标,底部标签栏背景颜色也与应用的背景颜色不一致。
修改 (tabs)/_layout.tsx 文件以添加标签栏图标:
- 从
@expo/vector-icons导入Ionicons图标集——这是一个包含常用图标集的库。 - 为
index和about路由都添加tabBarIcon。这个函数接收focused和color作为参数,并渲染图标组件。我们可以从图标集中提供自定义图标名称。 - 为
Tabs组件添加screenOptions.tabBarActiveTintColor,并将其设置为#ffd33d。这会在激活时更改标签栏图标和标签的颜色。
import { Tabs } from 'expo-router'; import Ionicons from '@expo/vector-icons/Ionicons'; export default function TabLayout() { return ( <Tabs screenOptions={{ tabBarActiveTintColor: '#ffd33d', }} > <Tabs.Screen name="index" options={{ title: 'Home', tabBarIcon: ({ color, focused }) => ( <Ionicons name={focused ? 'home-sharp' : 'home-outline'} color={color} size={24} /> ), }} /> <Tabs.Screen name="about" options={{ title: 'About', tabBarIcon: ({ color, focused }) => ( <Ionicons name={focused ? 'information-circle' : 'information-circle-outline'} color={color} size={24}/> ), }} /> </Tabs> ); }
我们再通过 screenOptions 属性更改标签栏和标题的背景颜色:
<Tabs screenOptions={{ tabBarActiveTintColor: '#ffd33d', headerStyle: { backgroundColor: '#25292e', }, headerShadowVisible: false, headerTintColor: '#fff', tabBarStyle: { backgroundColor: '#25292e', }, }} >
在上面的代码中:
- 使用
headerStyle属性将标题背景设置为#25292e。我们还使用headerShadowVisible禁用了标题阴影。 headerTintColor将#fff应用于标题文字tabBarStyle.backgroundColor将#25292e应用于标签栏
现在,我们的应用已经有了一个自定义的底部标签导航器:
概要
Chapter 2: Add navigation
我们已经成功为我们的应用添加了堆栈导航器和标签导航器。
在下一章中,我们将学习如何构建应用的第一个屏幕。