添加导航

在本章中,了解如何向 Expo 应用添加导航。


在本章中,我们将学习 Expo Router 的基础知识,以创建堆栈导航和带有两个选项卡的底部选项卡栏。

🌐 In this chapter, we'll learn Expo Router's fundamentals to create stack navigation and a bottom tab bar with two tabs.

观看:在你的通用 Expo 应用中添加导航
观看:在你的通用 Expo 应用中添加导航

Expo 路由基础知识

🌐 Expo Router basics

Expo Router 是一个基于文件的 React Native 和 Web 应用路由框架。它管理屏幕之间的导航,并在多个平台上使用相同的组件。要开始使用,我们需要了解以下约定:

🌐 Expo Router is a file-based routing framework for React Native and web apps. It manages navigation between screens and uses the same components across multiple platforms. To get started, we need to know about the following conventions:

  • 应用目录:一个只包含路由及其布局的特殊目录。添加到该目录的任何文件都会成为我们原生应用中的一个屏幕以及网页上的一个页面。
  • 根布局app/_layout.tsx 文件。它定义了共享的 UI 元素,如头部和选项卡栏,以确保在不同路由之间保持一致。
  • 文件命名约定Index 文件名,例如 index.tsx,与其父目录匹配,并且不添加路径段。例如,app 目录中的 index.tsx 文件对应 / 路由。
  • 一个 route 文件将一个 React 组件作为其默认值导出。它可以使用 .js.jsx.ts.tsx 扩展名。
  • Android、iOS 和 Web 共享统一的导航结构。

上述列表足够我们入门。有关完整功能列表,请参见 Expo Router 介绍

1

向堆栈中添加一个新屏幕

🌐 Add a new screen to the stack

让我们在 app 目录下创建一个名为 about.tsx 的新文件。当用户导航到 /about 路由时,它会显示屏幕名称。

🌐 Let's create a new file named about.tsx inside the app directory. It displays the screen name when the user navigates to the /about route.

app/about.tsx
import { Text, View, StyleSheet } from 'react-native'; export default function AboutScreen() { return ( <View style={styles.container}> <Text style={styles.text}>About screen</Text> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#25292e', justifyContent: 'center', alignItems: 'center', }, text: { color: '#fff', }, });

app/_layout.tsx 中:

🌐 Inside app/_layout.tsx:

  1. 添加一个 <Stack.Screen /> 组件和一个 options 属性来更新 /about 路由的标题。
  2. 通过添加 options 属性,将 /index 路由的标题更新为 Home
app/_layout.tsx
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> ); }
什么是

堆栈导航器是应用中在不同屏幕之间导航的基础。在 Android 上,堆栈路由会在当前屏幕上方进行动画显示。在 iOS 上,堆栈路由会从右侧进行动画显示。Expo Router 提供了一个 Stack 组件来创建导航堆栈,以添加新的路由。

🌐 A stack navigator is the foundation for navigating between different screens in an app. On Android, a stacked route animates on top of the current screen. On iOS, a stacked route animates from the right. Expo Router provides a Stack component to create a navigation stack to add new routes.

2

在屏幕之间导航

🌐 Navigate between screens

我们将使用 Expo Router 的 Link 组件从 /index 路由导航到 /about 路由。它是一个 React 组件,渲染一个带有指定 href 属性的 <Text>

🌐 We'll use Expo Router's Link component to navigate from the /index route to the /about route. It is a React component that renders a <Text> with a given href prop.

  1. index.tsx 中从 expo-router 导入 Link 组件。
  2. <Text> 组件后添加一个 Link 组件,并使用 /about 路由传递 href 属性。
  3. fontSizetextDecorationLinecolor 样式添加到 Link 组件。它接受与 <Text> 组件相同的属性。
app/index.tsx
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}>Home screen</Text> <Link href="/about" style={styles.button}> Go to About screen </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 路由:

🌐 Let's take a look at the changes in our app. Click on Link to navigate to the /about route:

3

添加未找到的路由

🌐 Add a not-found route

当某个路由不存在时,我们可以使用 +not-found 路由来显示备用屏幕。当我们希望在移动端导航到无效路由时显示自定义屏幕,而不是让应用崩溃或在网页上显示 404 错误时,这非常有用。Expo Router 使用一个特殊的 +not-found.tsx 文件来处理这种情况。

🌐 When a route doesn't exist, we can use a +not-found route to display a fallback screen. This is useful when we want to display a custom screen when navigating to an invalid route on mobile instead of crashing the app or display a 404 error on web. Expo Router uses a special +not-found.tsx file to handle this case.

  1. 在 app 目录中创建一个名为 +not-found.tsx 的新文件,以添加 NotFoundScreen 组件。
  2. Stack.Screen 添加 options 属性以显示此路由的自定义屏幕标题。
  3. 添加一个 Link 组件以导航到 / 路由,这是我们的后备路由。
app/+not-found.tsx
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}> Go back to Home screen! </Link> </View> </> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#25292e', justifyContent: 'center', alignItems: 'center', }, button: { fontSize: 20, textDecorationLine: 'underline', color: '#fff', }, });

要测试此功能,请在网页浏览器中导航到 http:localhost:8081/123 URL,因为在那里更改 URL 路径很方便。应用应显示 NotFoundScreen 组件:

🌐 To test this, navigate to http:localhost:8081/123 URL in the web browser since it is easy to change the URL path there. The app should display the NotFoundScreen component:

4

添加底部标签导航

🌐 Add a bottom tab navigator

此时,我们的 app 目录的文件结构如下所示:

🌐 At this point, the file structure of our app directory looks like the following:

app
_layout.tsxRoot layout
index.tsxmatches route '/'
about.tsxmatches route '/about'
+not-found.tsxmatches route any 404 route

我们将为应用添加一个底部标签导航,并重复使用现有的首页和关于页面来创建标签布局(这是许多社交媒体应用中常见的导航模式,例如 X 或 BlueSky)。我们还将在根布局中使用堆栈导航,以便 +not-found 路由显示在任何其他嵌套导航之上。

🌐 We'll add a bottom tab navigator to our app and reuse the existing Home and About screens to create a tab layout (a common navigation pattern in many social media apps like X or BlueSky). We'll also use the stack navigator in the Root layout so the +not-found route displays over any other nested navigators.

  1. app 目录下,添加一个 (tabs) 子目录。这个特殊目录用于将路由组合在一起,并在底部标签栏中显示它们。
  2. 在目录中创建一个 (tabs)/_layout.tsx 文件。它将用于定义选项卡布局,这与根布局是分开的。
  3. 将现有的 index.tsxabout.tsx 文件移动到 (tabs) 目录中。app 目录的结构将如下所示:
app
_layout.tsxRoot layout
+not-found.tsxmatches route any 404 route
(tabs)
  _layout.tsxTab layout
  index.tsxmatches route '/'
  about.tsxmatches route '/about'

更新根布局文件以添加一个 (tabs) 路由:

🌐 Update the Root layout file to add a (tabs) route:

app/_layout.tsx
import { Stack } from 'expo-router'; export default function RootLayout() { return ( <Stack> <Stack.Screen name="(tabs)" options={{ headerShown: false }} /> </Stack> ); }

(tabs)/_layout.tsx 中,添加一个 Tabs 组件来定义底部选项卡布局:

🌐 Inside (tabs)/_layout.tsx, add a Tabs component to define the bottom tab layout:

app/(tabs)/_layout.tsx
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> ); }

现在让我们来看一下我们的应用,看看新的底部标签:

🌐 Let's take a look at our app now to see the new bottom tabs:

5

更新底部标签导航栏外观

🌐 Update bottom tab navigator appearance

目前,底部标签导航在所有平台上看起来都一样,但与我们应用的风格不匹配。例如,标签栏或标题栏没有显示自定义图标,底部标签的背景颜色也与应用的背景颜色不一致。

🌐 Right now, the bottom tab navigator looks the same on all platforms but doesn't match the style of our app. For example, the tab bar or header doesn't display a custom icon, and the bottom tab background color doesn't match the app's background color.

修改 (tabs)/_layout.tsx 文件以添加标签栏图标:

🌐 Modify the (tabs)/_layout.tsx file to add tab bar icons:

  1. @expo/vector-icons 导入 Ionicons 图标集 — 这是一个包含流行图标集的库。
  2. tabBarIcon 添加到 indexabout 路由中。此函数以 focusedcolor 作为参数,并渲染图标组件。在图标集中,我们可以提供自定义的图标名称。
  3. screenOptions.tabBarActiveTintColor 添加到 Tabs 组件,并将其值设置为 #ffd33d。这将更改标签栏图标和标签在激活时的颜色。
app/(tabs)/_layout.tsx
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 属性来更改标签栏和标题的背景颜色:

🌐 Let's also change the background color of the tab bar and header using screenOptions prop:

app/(tabs)/_layout.tsx
<Tabs screenOptions={{ tabBarActiveTintColor: '#ffd33d', headerStyle: { backgroundColor: '#25292e', }, headerShadowVisible: false, headerTintColor: '#fff', tabBarStyle: { backgroundColor: '#25292e', }, }} >

在上面的代码中:

🌐 In the above code:

  • 页眉的背景使用 headerStyle 属性设置为 #25292e。我们还使用 headerShadowVisible 禁用了页眉的阴影。
  • headerTintColor#fff 应用于标题标签
  • tabBarStyle.backgroundColor#25292e 应用于标签栏

我们的应用现在有了自定义的底部标签导航器:

🌐 Our app now has a custom bottom tabs navigator:

概括

🌐 Summary

Chapter 2: Add navigation

我们已经成功地在应用中添加了堆栈导航和标签导航。

在下一章中,我们将学习如何构建应用的第一个界面。

Next: 构建你的应用的第一个界面