如何使用参数化路由作为GoRoute中StatefulShellRoute的根路由
解决GoRouter StatefulShellBranch参数化路由错误的方案
你遇到的错误是因为StatefulShellBranch的默认路由(分支内第一个路由)不允许带路径参数,调整路由层级结构就能解决这个问题。正确的思路是把参数化的/:id路由作为父级,在它内部嵌套StatefulShellRoute,让三个标签页的路由作为分支的默认无参数路由,既符合GoRouter规则,又能实现你需要的URL结构和有状态导航。
修改后的路由配置代码
final GlobalKey<NavigatorState> _rootNavigatorKey = GlobalKey<NavigatorState>(); final GlobalKey<NavigatorState> _pageANavigatorKey = GlobalKey<NavigatorState>(); final GlobalKey<NavigatorState> _pageBNavigatorKey = GlobalKey<NavigatorState>(); final GlobalKey<NavigatorState> _pageCNavigatorKey = GlobalKey<NavigatorState>(); final GoRouter _router = GoRouter( navigatorKey: _rootNavigatorKey, routes: <RouteBase>[ GoRoute( path: '/', builder: (BuildContext context, GoRouterState state) { return const MyHomePage(); }, routes: [ GoRoute( path: 'foo', builder: (BuildContext context, GoRouterState state) { return const FooListScreen(); }, routes: [ // 参数化:id作为父路由,内部嵌套StatefulShellRoute GoRoute( name: "fooDetails", path: ":id", builder: (context, state) { return StatefulShellRoute.indexedStack( builder: (context, state, navigationShell) { return Scaffold( body: navigationShell, bottomNavigationBar: BottomNavigationBar( currentIndex: navigationShell.currentIndex, onTap: (index) { navigationShell.goBranch( index, initialLocation: index == navigationShell.currentIndex, ); }, items: const [ BottomNavigationBarItem(icon: Icon(Icons.pageview), label: 'Page A'), BottomNavigationBarItem(icon: Icons.pages, label: 'Page B'), BottomNavigationBarItem(icon: Icons.pagination, label: 'Page C'), ], ), ); }, branches: [ StatefulShellBranch( navigatorKey: _pageANavigatorKey, routes: [ GoRoute( path: 'pageA', builder: (context, state) { final id = int.parse(state.pathParameters['id'] ?? '0'); return FooPageA(id: id); }, ), ], ), StatefulShellBranch( navigatorKey: _pageBNavigatorKey, routes: [ GoRoute( path: 'pageB', builder: (context, state) { final id = int.parse(state.pathParameters['id'] ?? '0'); return FooPageB(id: id); }, ), ], ), StatefulShellBranch( navigatorKey: _pageCNavigatorKey, routes: [ GoRoute( path: 'pageC', builder: (context, state) { final id = int.parse(state.pathParameters['id'] ?? '0'); return FooPageC(id: id); }, ), ], ), ], ).builder(context, state, null); }, // 进入/foo/:id时自动跳转到第一个标签页 redirect: (context, state) { final id = state.pathParameters['id']; if (id != null && state.uri.pathSegments.length == 2) { return '/foo/$id/pageA'; } return null; }, ), ], ), ], ), ], );
关键修改点说明
- 层级调整:把参数化的
/:id路由作为foo的子路由,内部嵌套StatefulShellRoute,让三个标签页路由作为分支的默认无参数路由,避开错误限制。 - 参数传递:标签页页面可通过
state.pathParameters['id']获取父路由的id参数,GoRouter会自动向上传递路径参数。 - 默认跳转:添加
redirect逻辑,用户进入/foo/:id时自动跳转到/foo/:id/pageA,确保进入详情页直接显示第一个标签页。 - 状态保留:
StatefulShellRoute.indexedStack会保持每个标签页的状态,切换时不会重新构建页面,满足有状态导航需求。
列表页跳转示例
在FooListScreen中跳转到详情页:
// 假设选中的foo id为1 context.goNamed('fooDetails', pathParameters: {'id': '1'});
内容的提问来源于stack exchange,提问作者user977208
相关产品推荐
相关产品推荐

