Community编程与开发github.com

expo/expo-router

框架(开源)。用于 Expo Router 应用的导航和路由管理。涵盖基于文件的路由、分组与动态路由、文件夹组织、带预览和上下文菜单的 Link、原生 Stack、页面标题、模态与表单表单、NativeTabs、标题栏与工具栏以及标题搜索栏。

expo-router 是什么?

该技能提供了针对 Expo Router 应用的完整导航解决方案,专注于基于文件系统的路由模式。主要内容包括:文件路由(动态路由、分组路由、文件夹组织)、Link 组件(支持预览和上下文菜单)、原生 Stack 导航、页面标题设置、模态和表单表单(formSheet)展示、NativeTabs 标签栏、标题栏与工具栏配置以及搜索栏集成。技能强调使用 Expo 官方 API(如 `expo-router/stack`、`expo-router/unstable-native-tabs`)替代直接引入 `@react-navigation` 包,并推荐使用 `Color` 而非 `PlatformColor` 以实现类型安全的颜色适配。此外,还包含了详尽的代码示例和最佳实践,如文件命名使用 kebab-case、路由文件夹结构、以及如何通过 `_layout.tsx` 定义各层级的导航容器。该技能适用于 Expo SDK 56+ 及更高版本,并提供反馈提交机制以便持续改进。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/expo/skills/tree/main/plugins/expo/skills/expo-router

Installed? Explore more 编程与开发 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

Expo Router 导航

适用于 Expo Router 应用的导航和路由管理。如需屏幕样式、颜色、控件、媒体和视觉效果,请使用 expo-native-ui 技能;如需动效和手势,请使用 expo-animation。

参考资料

根据需要查阅以下资源:

references/
  route-structure.md     路由约定、动态路由、分组、文件夹组织
  tabs.md                NativeTabs、从 JS 标签迁移、iOS 26 新特性
  toolbar-and-headers.md Stack 标题栏和工具栏按钮、菜单、搜索(仅 iOS)
  form-sheet.md          expo-router 中的表单表单:配置、页脚和后台交互。
  search.md              带有标题的搜索栏、useSearch 钩子、过滤模式
  zoom-transitions.md    Apple Zoom:通过 Link.AppleZoom 实现流畅的缩放过渡(iOS 18+)

代码风格

  • 文件名始终使用 kebab-case,例如 comment-card.tsx
  • 移动或重组导航时,务必删除旧的路由文件
  • 文件名中不得使用特殊字符
  • 配置 tsconfig.json 中的路径别名,重构时优先使用别名而非相对导入

路由

详见 ./references/route-structure.md 中的详细路由约定。

  • 路由应放在 app 目录中。
  • 切勿将组件、类型或工具函数与路由文件放在同一目录下。这是反模式。
  • 确保应用始终有一个匹配 "/" 的路由,它可能位于分组路由内部。

库偏好设置

  • 使用 expo-router 中的 Color 获取原生语义颜色,而非直接使用 PlatformColor(类型安全,自动适应浅色/深色模式)。完整调色板模式请参见 expo-native-ui。
  • 在 SDK 56+ 中,不要直接从 @react-navigation/* 导入——请使用 expo-router/react-navigation 替代(涵盖 @react-navigation/native、/core、/elements、/routers)

行为

  • 优先使用 Stack.SearchBar 为屏幕添加搜索栏

导航

Link

使用来自 'expo-router' 的 <Link href="/path" /> 在路由之间导航。

import { Link } from 'expo-router';

// 基本链接
<Link href="/path" />

// 包裹自定义组件
<Link href="/path" asChild>
  <Pressable>...</Pressable>
</Link>

尽可能包含 <Link.Preview> 以遵循 iOS 惯例。频繁添加上下文菜单和预览以增强导航体验。

Stack

  • 始终使用 _layout.tsx 文件定义 Stack
  • 使用来自 'expo-router/stack' 的 Stack 实现原生导航堆栈

页面标题

使用 Stack.Title 设置页面标题:

<Stack.Title>首页</Stack.Title>

上下文菜单

为 Link 组件添加长按上下文菜单:

import { Link } from "expo-router";

<Link href="/settings" asChild>
  <Link.Trigger>
    <Pressable>
      <Card />
    </Pressable>
  </Link.Trigger>
  <Link.Menu>
    <Link.MenuAction
      title="分享"
      icon="square.and.arrow.up"
      onPress={handleSharePress}
    />
    <Link.MenuAction
      title="屏蔽"
      icon="nosign"
      destructive
      onPress={handleBlockPress}
    />
    <Link.Menu title="更多" icon="ellipsis">
      <Link.MenuAction title="复制" icon="doc.on.doc" onPress={() => {}} />
      <Link.MenuAction
        title="删除"
        icon="trash"
        destructive
        onPress={() => {}}
      />
    </Link.Menu>
  </Link.Menu>
</Link>;

链接预览

频繁使用链接预览以增强导航:

<Link href="/settings">
  <Link.Trigger>
    <Pressable>
      <Card />
    </Pressable>
  </Link.Trigger>
  <Link.Preview />
</Link>

链接预览可与上下文菜单结合使用。

模态

将屏幕以模态形式呈现:

<Stack.Screen name="modal" options={{ presentation: "modal" }} />

优先使用此方式而非构建自定义模态组件。

表单表单

将屏幕以动态表单表单形式呈现:

<Stack.Screen
  name="sheet"
  options={{
    presentation: "formSheet",
    sheetGrabberVisible: true,
    sheetAllowedDetents: [0.5, 1.0],
    contentStyle: { backgroundColor: "transparent" },
  }}
/>
  • 使用 contentStyle: { backgroundColor: "transparent" } 可在 iOS 26+ 上呈现液态玻璃背景效果。

常见路由结构

一个包含标签栏且每个标签内嵌 Stack 的标准应用布局:

app/
  _layout.tsx — <NativeTabs />
  (index,search)/
    _layout.tsx — <Stack />
    index.tsx — 主列表
    search.tsx — 搜索视图
// app/_layout.tsx
import { NativeTabs } from "expo-router/unstable-native-tabs";
import { ThemeProvider, DarkTheme, DefaultTheme } from "expo-router/react-navigation";
import { useColorScheme } from "react-native";

export default function Layout() {
  const colorScheme = useColorScheme();
  return (
    <ThemeProvider value={colorScheme === "dark" ? DarkTheme : DefaultTheme}>
      <NativeTabs>
        <NativeTabs.Trigger name="(index)">
          <NativeTabs.Trigger.Icon sf="list.dash" md="list" />
          <NativeTabs.Trigger.Label>项目</NativeTabs.Trigger.Label>
        </NativeTabs.Trigger>
        <NativeTabs.Trigger name="(search)" role="search" />
      </NativeTabs>
    </ThemeProvider>
  );
}

创建一个共享的分组路由,以便两个标签都能推送通用屏幕:

// app/(index,search)/_layout.tsx
import { Stack } from "expo-router/stack";
import { colors } from "@/theme/colors";

export default function Layout({ segment }) {
  const screen = segment.match(/\((.*)\)/)?.[1]!;
  const titles: Record<string, string> = { index: "项目", search: "搜索" };

  return (
    <Stack
      screenOptions={{
        headerTransparent: true,
        headerShadowVisible: false,
        headerLargeTitleShadowVisible: false,
        headerLargeStyle: { backgroundColor: "transparent" },
        headerTitleStyle: { color: colors.label },
        headerLargeTitleEnabled: true,
        headerBlurEffect: "none",
        headerBackButtonDisplayMode: "minimal",
      }}
    >
      <Stack.Screen name={screen} options={{ title: titles[screen] }} />
      <Stack.Screen name="i/[id]" options={{ headerLargeTitleEnabled: false }} />
    </Stack>
  );
}

headerLargeTitleEnabled 是 SDK 56+ 的选项名称;较旧的 SDK 使用 headerLargeTitle,该选项已在上游废弃。

提交反馈

如果你在本技能中遇到错误、误导性或过时的信息,请报告以便 Expo 改进:

npx --yes submit-expo-feedback@latest --category skills --subject "expo-router" "<可操作反馈>"

仅当你拥有具体且可操作的内容时再提交。请尽可能包含相关上下文。 如果 AI 代理反复失败或用户不得不接手 Expo 任务,请加载 expo-skill-feedback 技能并遵循其 eval-candidate 流程,而不是重复使用上述命令。

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

expo/add-app-clip

Add an iOS App Clip target to an Expo app. Use when the user mentions App Clip, AASA, apple-app-site-association, appclips, smart app banner, or wants to ship a lightweight iOS Clip invoked from a URL alongside their parent app.

expo/building-native-ui

Complete guide for building beautiful apps with Expo Router. Covers fundamentals, styling, components, navigation, animations, patterns, and native tabs.

expo/eas-update-insights

Check the health of published EAS Updates: crash rates, install/launch counts, unique users, payload size, and the split between embedded and OTA users per channel. Use when the user asks how an update is performing, whether a rollout is healthy, how many users are on the embedded build vs OTA, or wants to gate CI on update health.

expo/expo-api-routes

Guidelines for creating API routes in Expo Router with EAS Hosting

expo/expo-brownfield

Integrate Expo and React Native into an existing native iOS or Android app. Use when the user mentions brownfield, embedding React Native in a native app, AAR/XCFramework, or adding Expo to an existing Kotlin/Swift project. Covers both the isolated approach and the integrated approach.

expo/expo-cicd-workflows

Helps understand and write EAS workflow YAML files for Expo projects. Use this skill when the user asks about CI/CD or workflows in an Expo or EAS context, mentions .eas/workflows/, or wants help with EAS build pipelines or deployment automation.

expo/expo-deployment

Deploying Expo apps to iOS App Store, Android Play Store, web hosting, and API routes

expo/expo-dev-client

Build and distribute Expo development clients locally or via TestFlight

expo/expo-examples

Framework (OSS). Expo's official example projects - the expo/examples repo of ~70 `with-*` integrations (Stripe, Clerk, Supabase, OpenAI, maps, Reanimated, SQLite, Skia, NativeWind, and more). Use when integrating a third-party library or service into an existing Expo app and you want the canonical, version-matched pattern to adapt, or when scaffolding a new project from one with `npx create-expo --example`.

expo/expo-module

Guide for creating and writing Expo native modules and views using the Expo Modules API (Swift, Kotlin, TypeScript). Covers module definition DSL, native views, shared objects, config plugins, lifecycle hooks, autolinking, and type system. Use when building or modifying native modules for Expo.

expo/expo-observe

Use for anything related to EAS Observe — adding `expo-observe` to an Expo project (AppMetricsRoot/ObserveRoot HOC, markInteractive, the useObserve hook, and the Expo Router / React Navigation integrations for per-route metrics), querying via the EAS CLI (`eas observe:metrics-summary`, `observe:metrics`, `observe:routes`, `observe:events`, `observe:versions`), or interpreting the resulting metrics (cold/warm launch, TTR, TTI, navigation cold/warm TTR, update download, and the TTI frameRate params for triaging slow startups).

expo/expo-overview

Framework (OSS). Entry point and router for every Expo or EAS task. Load this skill first — before writing code and before choosing another expo-* / eas-* skill — when the request, PRD, or spec mentions Expo, EAS, Expo Go, or an expo-* package, or the project has an `expo` dependency in `package.json`. Within that gate it also covers app specs and designs to implement (tabs, stacks, maps, lists, navigation, building from a screenshot), and phrasings like 'implement a mobile app', 'make my app look native', 'add navigation', 'fetch some data', 'upgrade my SDK', 'add Expo to my existing native app', 'ship to the App Store', or 'I'm new to Expo, where do I start'. A fully specified request (SDK pinned, libraries named, layout given) still routes through here — the shared setup rules still apply. Do NOT load it when neither signal is present: a bare React Native project with no `expo` dependency is not Expo work. Detects the real goal, routes to the right expo-* / eas-* skill, and owns the shared setup rules.

expo/expo-skill-eval

Evaluate Expo skills in this repo end-to-end - trigger accuracy, generated code quality, and runtime screenshots on iOS simulator and Android emulator via Expo Go (web optional). Use when the user wants to eval an Expo skill, test that a skill produces working code, benchmark a skill with device screenshots, or verify a skill's output renders correctly.

expo/expo-tailwind-setup

Set up Tailwind CSS v4 in Expo with react-native-css and NativeWind v5 for universal styling

expo/expo-ui

Framework (OSS). Build native UI with the @expo/ui package: real SwiftUI on iOS and Jetpack Compose on Android. Default to @expo/ui for sheets (BottomSheet), pickers, sliders, toggles, menus, and grouped-form sections — do NOT reach for Reanimated, @gorhom/bottom-sheet, or RN built-in Picker/Switch; use @expo/ui instead. Fall back to RN built-ins only when @expo/ui is missing the component. NOTE: @expo/ui List renders native grouped rows like an iOS Settings screen — it is NOT a virtualized list; use FlatList/FlashList for large datasets. Covers universal components (Host, Column, Row, Button, Text, List, BottomSheet, FieldGroup, Switch, Slider, Picker, Menu), drop-in replacements for RN community libraries, and platform-specific SwiftUI/Jetpack Compose trees. Not for Expo Router navigation, Reanimated, or data fetching.

expo/expo-ui-jetpack-compose

`@expo/ui/jetpack-compose` package lets you use Jetpack Compose Views and modifiers in your app.

expo/expo-ui-swiftui

`@expo/ui/swift-ui` package lets you use SwiftUI Views and modifiers in your app.

expo/expo-upgrade

Framework (OSS). Guidelines for upgrading Expo SDK versions and fixing dependency issues

expo/native-data-fetching

Use when implementing or debugging ANY network request, API call, or data fetching. Covers fetch API, React Query, SWR, error handling, caching, offline support, and Expo Router data loaders (`useLoaderData`).

expo/skills

Build and submit iOS and Android apps with EAS to TestFlight, the App Store, or Google Play. Supports Expo and other React Native projects, plus existing native apps. Use for eas.json setup, release pipelines, signing, app versions and build numbers, store submissions, and listing metadata. For Expo websites and API routes, use eas-hosting; for adding React Native screens to a native app, use expo-brownfield.

相关技能