JavaScript 选项卡

编辑页面

了解如何在 Expo Router 中使用 JavaScript 选项卡布局(React Navigation 底部选项卡)。


For the complete documentation index, see llms.txt. Use this Use this file to discover all available pages.

使用 Expo Router 的 JavaScript 标签导航器
使用 Expo Router 的 JavaScript 标签导航器

配置标签图标、嵌套导航器并管理导航历史。

标签页是应用中不同部分之间导航的一种常见方式。Expo Router 提供了一个标签页布局,帮助你在应用底部创建标签栏。最快的入门方式是使用模板。请参阅 快速开始安装 开始使用。

多种标签页布局

Expo Router 提供三种类型的标签导航器:

  • JavaScript 标签页:使用 React Navigation 的底部标签页实现,如果你已经使用过 React Navigation,就会觉得 API 很熟悉。
  • 原生标签页:使用平台原生的标签栏,提供原生的外观和体验。
  • 自定义标签页:提供来自 expo-router/ui 的无头标签组件,用于构建完全自定义的标签布局,以实现复杂的 UI 模式。

本指南介绍的是 JavaScript 标签页 布局。其他标签页布局请参阅:

原生标签页

如果你想让标签栏拥有原生的外观和体验,请查看原生标签页。

自定义标签页

如果你的应用需要完全自定义的设计,而系统标签页无法实现,请查看自定义标签页。

开始使用 JavaScript 标签页

你可以使用基于文件的路由来创建标签页布局。下面是一个文件结构示例:

src
app
  _layout.tsx
  (tabs)
   _layout.tsx
   index.tsx
   settings.tsx

这种文件结构会生成一个底部带有标签栏的布局。该标签栏将包含两个标签:HomeSettings

你可以使用 src/app/_layout.tsx 文件来定义应用的根布局:

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

(tabs) 目录是一个特殊的目录名,它会告诉 Expo Router 使用 Tabs 布局。

从文件结构来看,(tabs) 目录包含三个文件。第一个是 (tabs)/_layout.tsx。这个文件是标签栏以及每个标签的主布局文件。在其中,你可以控制标签栏和每个标签按钮的外观与行为。

src/app/(tabs)/_layout.tsx
import FontAwesome from '@expo/vector-icons/FontAwesome'; import { Tabs } from 'expo-router'; export default function TabLayout() { return ( <Tabs screenOptions={{ tabBarActiveTintColor: 'blue' }}> <Tabs.Screen name="index" options={{ title: '首页', tabBarIcon: ({ color }) => <FontAwesome size={28} name="home" color={color} />, }} /> <Tabs.Screen name="settings" options={{ title: '设置', tabBarIcon: ({ color }) => <FontAwesome size={28} name="cog" color={color} />, }} /> </Tabs> ); }

最后,你有两个组成标签内容的标签文件:src/app/(tabs)/index.tsxsrc/app/(tabs)/settings.tsx

src/app/(tabs)/index.tsx & src/app/(tabs)/settings.tsx
import { View, Text, StyleSheet } from 'react-native'; export default function Tab() { return ( <View style={styles.container}> <Text>标签 [Home|Settings]</Text> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, });

名为 index.tsx 的标签文件是应用加载时的默认标签。第二个标签文件 settings.tsx 展示了如何向标签栏添加更多标签。

标签栏选项

Expo Router 中的 JavaScript 标签页扩展自 React Navigation 的 Bottom Tabs Navigator。可用的具体 API 取决于你的版本。例如,Expo Router v6 扩展了 Bottom Tabs Navigator v7。请检查你的版本以确保兼容性,然后你可以使用相同的配置属性来自定义底部标签栏和单个标签页。例如:

src/app/(tabs)/_layout.tsx
import { Tabs } from 'expo-router'; export default function TabLayout() { return ( <Tabs screenOptions={ { // 在这里应用于所有标签页 } }> <Tabs.Screen name="index" options={ { // 或者在这里应用于某一个标签页 } } /> </Tabs> ); }

支持的标签栏选项如下:

Tab bar options
OptionPlatformDescription
tabBarAccessibilityLabel
Android
iOS

Accessibility label for the tab button. This is read by the screen reader when the user taps the tab. It's recommended to set this if you don't have a label for the tab.

tabBarActiveBackgroundColor
Android
iOS

Background color for the active tab.

tabBarActiveTintColor
Android
iOS

Color for the icon and label in the active tab.

tabBarBackground
Android
iOS

Function which returns a React Element to use as background for the tab bar. You could render an image, a gradient, blur view etc.:

import { BlurView } from 'expo-blur'; // ... <Tab.Navigator screenOptions={{ tabBarStyle: { position: 'absolute' }, tabBarBackground: () => ( <BlurView tint="light" intensity={100} style={StyleSheet.absoluteFill} /> ), }} >

When using BlurView, make sure to set position: 'absolute' in tabBarStyle as well. You'd also need to use useBottomTabBarHeight to add bottom padding to your content.

tabBarBadge
Android
iOS

Text to show in a badge on the tab icon. Accepts a string or a number.

tabBarBadgeStyle
Android
iOS

Style for the badge on the tab icon. You can specify a background color or text color here.

tabBarButton
Android
iOS

Function which returns a React element to render as the tab bar button. It wraps the icon and label. Renders Pressable by default.

You can specify a custom implementation here:

tabBarButton: (props) => <TouchableOpacity {...props} />;
tabBarButtonTestID
Android
iOS

ID to locate this tab button in tests.

tabBarHideOnKeyboard
Android
iOS

Whether the tab bar is hidden when the keyboard opens. Defaults to false.

tabBarIcon
Android
iOS

Function that given { focused: boolean, color: string, size: number } returns a React.Node, to display in the tab bar.

tabBarIconStyle
Android
iOS

Style object for the tab icon.

tabBarInactiveBackgroundColor
Android
iOS

Background color for the inactive tabs.

tabBarInactiveTintColor
Android
iOS

Color for the icon and label in the inactive tabs.

tabBarItemStyle
Android
iOS

Style object for the tab item container.

tabBarLabel
Android
iOS

Title string of a tab displayed in the tab bar or a function that given { focused: boolean, color: string } returns a React.Node, to display in tab bar. When undefined, scene title is used. To hide, see tabBarShowLabel.

tabBarLabelPosition
Android
iOS

Whether the label is shown below the icon or beside the icon.

By default, the position is chosen automatically based on device width.

  • below-icon: the label is shown below the icon (typical for iPhones)

  • beside-icon the label is shown next to the icon (typical for iPad)

tabBarLabelStyle
Android
iOS

Style object for the tab label.

tabBarPosition
Android
iOS

Position of the tab bar. Available values are:

  • bottom (Default)
  • top
  • left
  • right

When the tab bar is positioned on the left or right, it is styled as a sidebar. This can be useful when you want to show a sidebar on larger screens and a bottom tab bar on smaller screens:

<Tab.Navigator screenOptions={{ tabBarPosition: dimensions.width < 600 ? 'bottom' : 'left', tabBarLabelPosition: 'below-icon', }} >
tabBarShowLabel
Android
iOS

Whether the tab label should be visible. Defaults to true.

tabBarStyle
Android
iOS

Style object for the tab bar. You can configure styles such as background color here.

To show your screen under the tab bar, you can set the position style to absolute:

<Tab.Navigator screenOptions={{ tabBarStyle: { position: 'absolute' }, }} >

You also might need to add a bottom margin to your content if you have an absolutely positioned tab bar. React Navigation won't do it automatically. See useBottomTabBarHeight for more details.

tabBarVariant
Android
iOS

Variant of the tab bar. Available values are:

  • uikit (Default) - The tab bar will be styled according to the iOS UIKit guidelines.
  • material - The tab bar will be styled according to the Material Design guidelines.

The material variant is currently only supported when the tabBarPosition is set to left or right.

如需更多细节和与导航器相关的示例,请参阅 React Navigation 的 Bottom Tabs Navigator 文档

高级

隐藏某个标签页

有时你希望某个路由存在,但不显示在标签栏中。你可以传入 href: null 来禁用该按钮:

src/app/(tabs)/_layout.tsx
import { Tabs } from 'expo-router'; export default function TabLayout() { return ( <Tabs> <Tabs.Screen name="index" options={{ href: null, }} /> </Tabs> ); }

动态路由

你可以在标签栏中使用动态路由。例如,你有一个 [user] 标签,用于显示用户的个人资料。你可以使用 href 选项链接到特定用户的个人资料。

src/app/(tabs)/_layout.tsx
import { Tabs } from 'expo-router'; export default function TabLayout() { return ( <Tabs> <Tabs.Screen // 动态路由的名称。 name="[user]" options={{ // 确保该标签始终链接到同一个 href。 href: '/evanbacon', // 或者你也可以使用 href 对象。 href: { pathname: '/[user]', params: { user: 'evanbacon', }, }, }} /> </Tabs> ); }

注意:在标签布局中添加动态路由时,请确保所定义的动态路由是唯一的。你不能为同一个动态路由设置两个屏幕。例如,你不能有两个 [user] 标签。如果你需要多个动态路由,请创建一个自定义导航器。