移动/游戏
在 Expo Router 项目中实现文件式路由、原生导航…
在 Expo/React Native 应用中使用 Expo Router 组织路由、Stack、NativeTabs、Link、模态和表单 sheet,获得符合 iOS 约定的原生导航体验。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
在 Expo Router 项目中实现文特定
解决思路
- 需要屏幕样式、颜色、控件、媒体和视觉效果时,改用 `expo-native-ui` skill;需要动效和手势时,改用 `expo-animation` skill。
- 按需查阅 references 下的资料:`references/route-structure.md`(路由约定、动态路由、分组、文件夹组织)、`references/tabs.md`(NativeTabs、从 JS tabs 迁移、iOS 26 特性)、`references/toolbar-and-headers.md`(Stack headers 和 toolbar buttons、menus、search,iOS only)、`references/form-sheet.md`(expo-router 中的 form sheets:配置、footers 和背景交互)、`references/search.md`(带 header 的搜索栏、useSearch hook、过滤模式)、`references/zoom-transitions.md`(Apple Zoom:使用 Link.AppleZoom 的流体缩放转场,iOS 18+)。
- 文件名始终使用 kebab-case,例如 `comment-card.tsx`。
- 移动或重构导航时,始终删除旧的路由文件。
- 文件名中绝不使用特殊字符。
- 在 `tsconfig.json` 中配置 path aliases,重构时优先使用别名而不是相对导入。
- 路由放在 `app` 目录中。
- 绝不要将组件、类型或工具函数与路由共置于 `app` 目录内;这是反模式。
- 确保应用始终有一个匹配 `/` 的路由,它可以位于 group route 内。
- 使用 `expo-router` 的 `Color` 获取原生语义颜色,而不是原始 `PlatformColor`(类型安全,自动适配 light/dark);完整调色板模式见 `expo-native-ui`。
- 在 SDK 56+ 中,绝不要直接从 `@react-navigation/*` 导入;改用 `expo-router/react-navigation`(覆盖 `@react-navigation/native`、`/core`、`/elements`、`/routers`)。
- 优先使用 `Stack.SearchBar` 给屏幕添加搜索栏。
- 使用 `expo-router` 的 `<Link href="/path" />` 在路由间导航。
- 包裹自定义组件时使用 `<Link href="/path" asChild><Pressable>...</Pressable></Link>`。
- 尽可能包含 `<Link.Preview />` 以遵循 iOS 约定;经常添加上下文菜单和预览以增强导航。
- 始终使用 `_layout.tsx` 文件定义 stacks。
- 使用来自 `expo-router/stack` 的 `Stack` 实现原生导航 stacks。
- 使用 `Stack.Title` 设置页面标题,例如 `<Stack.Title>Home</Stack.Title>`。
- 给 Link 组件添加长按上下文菜单:用 `<Link href="/settings" asChild>`,在 `<Link.Trigger>` 中包裹 `<Pressable><Card /></Pressable>`,并在 `<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">` 含 `Copy`/`Delete` 等 `Link.MenuAction`。
- 用 link previews 增强导航:`<Link href="/settings">` 内使用 `<Link.Trigger>` 包裹 `<Pressable><Card /></Pressable>`,并加入 `<Link.Preview />`。
- Link preview 可以与上下文菜单一起使用。
- 用 `<Stack.Screen name="modal" options={{ presentation: "modal" }} />` 将屏幕呈现为 modal;优先使用它,而不是构建自定义 modal 组件。
- 用 `<Stack.Screen name="sheet" options={{ presentation: "formSheet", sheetGrabberVisible: true, sheetAllowedDetents: [0.5, 1.0], contentStyle: { backgroundColor: "transparent" } }} />` 将屏幕呈现为动态 form sheet。
- 使用 `contentStyle: { backgroundColor: "transparent" }` 可让背景在 iOS 26+ 呈现 liquid glass。
- 采用常见路由结构:`app/_layout.tsx` 使用 `<NativeTabs />`,`app/(index,search)/_layout.tsx` 使用 `<Stack />`,其中 `index.tsx` 为主列表,`search.tsx` 为搜索视图。
- 在 `app/_layout.tsx` 中,从 `expo-router/unstable-native-tabs` 导入 `NativeTabs`,从 `expo-router/react-navigation` 导入 `ThemeProvider, DarkTheme, DefaultTheme`,使用 `useColorScheme`,根据 colorScheme 选择 DarkTheme 或 DefaultTheme 包裹 `ThemeProvider`,然后用 `NativeTabs`,其中 `<NativeTabs.Trigger name="(index)">` 含 `<NativeTabs.Trigger.Icon sf="list.dash" md="list" />` 和 `<NativeTabs.Trigger.Label>Items</NativeTabs.Trigger.Label>`,另一个 `<NativeTabs.Trigger name="(search)" role="search" />`。
- 创建共享 group route 让两个 tab 都能 push 公共屏幕:在 `app/(index,search)/_layout.tsx` 中从 `expo-router/stack` 导入 `Stack`,从 `@/theme/colors` 导入 `colors`,导出 `Layout({ segment })`,用 `segment.match(/\((.*)\)/)?.[1]!` 取得 `screen`,定义 `titles: Record<string, string> = { index: "Items", search: "Search" }`。
- 在该共享 layout 的 `<Stack>` 上设置 `screenOptions`:`headerTransparent: true`、`headerShadowVisible: false`、`headerLargeTitleShadowVisible: false`、`headerLargeStyle: { backgroundColor: "transparent" }`、`headerTitleStyle: { color: colors.label }`、`headerLargeTitleEnabled: true`、`headerBlurEffect: "none"`、`headerBackButtonDisplayMode: "minimal"`。
- 在该共享 layout 中添加 `<Stack.Screen name={screen} options={{ title: titles[screen] }} />` 和 `<Stack.Screen name="i/[id]" options={{ headerLargeTitleEnabled: false }} />`。
- `headerLargeTitleEnabled` 是 SDK 56+ 的选项名;更老 SDK 使用 `headerLargeTitle`,它在上游已废弃。
- 如果遇到错误、误导性或过时信息,运行 `npx --yes submit-expo-feedback@latest --category skills --subject "expo-router" "<actionable feedback>"` 向 Expo 反馈以改进 skill。
- 仅在有具体且可操作的内容时提交反馈;尽量包含相关上下文。
- 如果 AI agent 反复失败或用户不得不接管 Expo 任务,加载 `expo-skill-feedback` skill 并遵循其 eval-candidate 流程,而不是复用上述命令。
适用边界 · 注意事项
- 不适用于不使用 Expo Router 的项目,例如纯 React Native CLI、单独使用 React Navigation 或其他 Web 路由方案。
- 若只做屏幕样式、颜色、控件或动效手势,不要用本技能,分别转用 `expo-native-ui` 或 `expo-animation`。
- 若使用 SDK <56 或非 iOS 目标,部分 iOS 专有/较新 API(如 form sheet liquid glass、Apple Zoom、NativeTabs 的 iOS 26 特性)不可用或需要降级。