如何导航到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的当前配置,动态获取当前路由所属分支的默认路由:
- 定义分支与默认路由的映射关系:
// 存储每个分支navigatorKey对应的默认路由路径 final Map<GlobalKey<NavigatorState>, String> branchDefaultRoutes = { key1: path1, key2: path4, };
- 在返回按钮逻辑中解析并导航:
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
相关产品推荐
相关产品推荐

