mcpField
E
expo-router

expo-router

github.com/expo开发3.5k28.8k 次安装今天更新
代码仓库

关于 expo-router

expo-router 是面向 Expo Router 应用开发者的导航技能,介绍路由组织方式及 Stack、标签页、链接、模态页和表单页等原生导航模式。

主要功能

  1. 01路由结构规范
  2. 02Stack 与标签页导航指导
  3. 03链接与深层导航模式
  4. 04模态页与表单页指导
  5. 05页眉与搜索模式

适用场景

  1. 01组织 Expo 应用路由
  2. 02构建 Stack 或标签页导航
  3. 03以模态页或表单页呈现屏幕

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/expo/skills --skill expo-router

安装后在 Claude Code 中输入/expo-router确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

agents/
openai.yaml
references/
form-sheet.md
route-structure.md
search.md
tabs.md
toolbar-and-headers.md
zoom-transitions.md

详细介绍

Expo Router 导航

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

参考资料

按需查阅以下资源:

references/
  route-structure.md     Route conventions, dynamic routes, groups, folder organization
  tabs.md                NativeTabs, migration from JS tabs, iOS 26 features
  toolbar-and-headers.md Stack headers and toolbar buttons, menus, search (iOS only)
  form-sheet.md          Form sheets in expo-router: configuration, footers and background interaction.
  search.md              Search bar with headers, useSearch hook, filtering patterns
  zoom-transitions.md    Apple Zoom: fluid zoom transitions with Link.AppleZoom (iOS 18+)

代码风格

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

路由

详细的路由约定请参阅 ./references/route-structure.md。

  • 路由应放在 app 目录中。
  • 不要将组件、类型或实用工具放在 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';

// Basic link
<Link href="/path" />

// Wrapping custom components
<Link href="/path" asChild>
  <Pressable>...</Pressable>
</Link>

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

Stack

  • 始终使用 _layout.tsx 文件定义堆栈
  • 使用来自 'expo-router/stack' 的 Stack 构建原生导航堆栈
页面标题

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

<Stack.Title>Home</Stack.Title>

上下文菜单

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

import { Link } from "expo-router";

<Link href="/settings" asChild>
  <Link.Trigger>
    <Pressable>
      <Card />
    </Pressable>
  </Link.Trigger>
  <Link.Menu>
    <Link.MenuAction
      title="Share"
      icon="square.and.arrow.up"
      onPress={handleSharePress}
    />
    <Link.MenuAction
      title="Block"
      icon="nosign"
      destructive
      onPress={handleBlockPress}
    />
    <Link.Menu title="More" icon="ellipsis">
      <Link.MenuAction title="Copy" icon="doc.on.doc" onPress={() => {}} />
      <Link.MenuAction
        title="Delete"
        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+ 上呈现液态玻璃效果。

常见路由结构

包含标签页,且每个标签页中都有堆栈的标准应用布局:

app/
  _layout.tsx — <NativeTabs />
  (index,search)/
    _layout.tsx — <Stack />
    index.tsx — Main list
    search.tsx — Search view
// 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>Items</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: "Items", search: "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 @expo/agent-cli@latest feedback --category skills --subject "expo-router" "<actionable feedback>"

只有在有具体且可执行的反馈时才提交。请尽可能提供相关背景信息。 如果 Agent 反复无法完成 Expo 任务,或用户不得不介入,请使用 --category evals 和相关 Expo 软件包或命令作为 --subject,简要报告任务、预期结果及问题所在。

评论

支持 Markdown