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

如何导航到GoRouter中StatefulShellBranch的首个/默认路由

GoRouter StatefulShellBranch 默认路由导航实现方案

需求场景

使用GoRouter的StatefulShellRoute和StatefulShellBranch时,希望实现:当通过深链接直接进入分支内的路由(如path5对应的Widget5),点击返回按钮时,若当前路由栈无法pop(无上级路由),则自动导航到该分支的首个/默认路由(如path4对应的Widget4)。

现有路由与组件代码

路由定义

router = GoRouter(
    routes: [
      StatefulShellRoute.indexedStack(
        parentNavigatorKey: parentNavigatorKey,
        branches: [
          StatefulShellBranch(
            navigatorKey: key1,
            routes: [
              GoRoute(
                path: path1,
                pageBuilder: (context, state) {
                  return Widget1();
                },
                routes: <RouteBase>[
                  GoRoute(
                    path: path2,
                    pageBuilder: (context, state) {
                      return Widget2();
                    },
                  ),
                  GoRoute(
                    path: path3,
                    pageBuilder: (context, state) {
                      return Widget3();
                    },
                  ),
                ],
              ),
            ],
          ),
          StatefulShellBranch(
            navigatorKey: key2,
            routes: [
              GoRoute(
                path: path4,
                pageBuilder: (context, state) {
                  return Widget4();
                },
              ),
              GoRoute(
                path: path5,
                pageBuilder: (context, state) {
                  return Widget5();
                },
              ),
            ],
          ),
        ],
      ),
      GoRoute(
        parentNavigatorKey: parentNavigatorKey,
        path: path6,
        pageBuilder: (context, state) {
          return Widget6();
        },
      ),
    ]);

组件返回按钮代码

// Inside Widget5
class BackButton extends StatelessWidget {
  ...
  onPressed() {
    if (router.canPop()) {
      router.pop();
    } else {
      // TODO: Navigate to default route of StatefulShellBranch
      final defaultRoute = router
          .routerDelegate
          .currentConfiguration.???();
    }
  }
  ...
}

解决方案

方案1:规范路由结构(推荐)

将分支内的路由改为默认路由的嵌套子路由,深链接进入子路由时,路由栈会自动包含默认路由,pop即可直接返回。

修改第二个分支的路由定义:

StatefulShellBranch(
  navigatorKey: key2,
  routes: [
    GoRoute(
      path: path4,
      pageBuilder: (context, state) {
        return Widget4();
      },
      // 将path5作为path4的子路由
      routes: [
        GoRoute(
          path: path5,
          pageBuilder: (context, state) {
            return Widget5();
          },
        ),
      ],
    ),
  ],
),

此时通过深链接进入path5时,路由栈为path4 -> path5,点击返回按钮执行router.pop()即可回到path4,无需额外逻辑。

方案2:硬编码默认路由路径(简单直接)

若路由结构无法调整,可直接在返回按钮逻辑中指定当前分支的默认路由路径:

onPressed() {
  if (router.canPop()) {
    router.pop();
  } else {
    // 直接导航到当前分支的默认路由path4
    router.go(path4);
  }
}

优点:实现简单;缺点:路由结构变更时需手动同步修改代码,灵活性差。

方案3:动态解析分支默认路由(灵活适配)

通过解析GoRouter的当前配置,动态获取当前路由所属分支的默认路由:

  1. 定义分支与默认路由的映射关系:
// 存储每个分支navigatorKey对应的默认路由路径
final Map<GlobalKey<NavigatorState>, String> branchDefaultRoutes = {
  key1: path1,
  key2: path4,
};
  1. 在返回按钮逻辑中解析并导航:
onPressed() {
  if (router.canPop()) {
    router.pop();
  } else {
    // 获取当前StatefulShellRoute匹配项
    final shellMatch = router.routerDelegate.currentConfiguration
        .whereType<StatefulShellRouteMatch>()
        .firstOrNull;
    
    if (shellMatch != null) {
      // 找到当前路由所属的分支
      final currentBranch = shellMatch.branchMatches
          .firstWhere((match) => match.route.path == path5)
          .branch;
      
      // 获取分支默认路由并导航
      final defaultPath = branchDefaultRoutes[currentBranch.navigatorKey];
      if (defaultPath != null) {
        router.go(defaultPath);
      }
    }
  }
}

优点:路由结构变更时只需更新映射表,无需修改业务逻辑;缺点:需要额外维护映射关系。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 08:19:53