You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GoRouter嵌套路由重复问题:统一电影详情路由并保留根菜单?

解决StatefulShellRoute下电影应用导航的三个问题

针对你遇到的路径不统一、路由重复、递归跳转问题,我们可以通过将共享路由挂载到StatefulShellRoute的全局子路由中,配合导航器key控制跳转上下文来解决,具体方案如下:

核心思路

  1. 把电影详情这类全局共享路由抽离成独立配置,挂载在StatefulShellRoute的routes参数下(而非每个分支内部),确保路径统一且无需重复定义;
  2. 使用导航器key区分根导航(控制底部菜单)和分支导航,避免跳转时出现递归嵌套;

完整代码示例

首先抽离共享的电影详情路由:

// 全局共享的电影详情路由,只需定义一次
final GoRoute movieDetailRoute = GoRoute(
  path: '/movies/:id',
  builder: (context, state) {
    final movieId = state.pathParameters['id']!;
    return MovieDetailScreen(movieId: movieId);
  },
  // 后续扩展子路由(如评论页)只需在这里添加
  routes: [
    GoRoute(
      path: 'reviews',
      builder: (context, state) => MovieReviewsScreen(movieId: state.pathParameters['id']!),
    ),
  ],
);

然后配置GoRouter:

// 导航器key,区分根导航和各分支导航
final _rootNavigatorKey = GlobalKey<NavigatorState>();
final _homeNavigatorKey = GlobalKey<NavigatorState>();
final _searchNavigatorKey = GlobalKey<NavigatorState>();

final router = GoRouter(
  navigatorKey: _rootNavigatorKey,
  routes: [
    StatefulShellRoute.indexedStack(
      navigatorKey: _rootNavigatorKey, // 根导航器,负责底部菜单的展示
      branches: [
        StatefulShellBranch(
          navigatorKey: _homeNavigatorKey,
          routes: [
            GoRoute(
              path: '/',
              builder: (context, state) => const HomeScreen(),
            ),
          ],
        ),
        StatefulShellBranch(
          navigatorKey: _searchNavigatorKey,
          routes: [
            GoRoute(
              path: '/search',
              builder: (context, state) => const SearchScreen(),
            ),
          ],
        ),
      ],
      // 全局共享路由挂载在这里,所有分支都能访问,且路径不受分支影响
      routes: [
        movieDetailRoute,
      ],
    ),
  ],
);

问题逐一解决说明

  • 路径统一:电影详情路由属于StatefulShellRoute的全局子路由,无论从首页还是搜索页跳转,路径始终为/movies/:id,不会带上/search这类分支前缀;
  • 路由重复:共享路由只需定义一次,后续扩展子路由也只需在抽离的配置中修改,无需在每个分支里重复编写;
  • 递归跳转问题:在电影详情页跳转另一部电影时,使用根导航器上下文跳转,避免在当前分支导航栈中嵌套新的详情页:
    // 在MovieDetailScreen中跳转新电影
    GoRouter.of(context).push('/movies/$newMovieId');
    // 或者直接指定根导航器key(更明确)
    _rootNavigatorKey.currentState?.pushNamed('/movies/$newMovieId');
    

关键注意点

不要把共享路由放在StatefulShellRoute外面,否则跳转时会完全替换掉包含底部菜单的Shell结构;而挂载在StatefulShellRoute的routes参数下,会在保留底部菜单的基础上,在其上方叠加详情页,符合需求。

内容的提问来源于stack exchange,提问作者Edgar Gataullin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 05:53:12