拓冰建站拓冰建站
首页 / 资讯中心 / 正文

go_router 路由配置完全指南:从 GoRoute 基础配置到状态化嵌套导航

go_router 路由配置完全指南从 GoRoute 基础配置到状态化嵌套导航【免费下载链接】packagesA collection of useful packages maintained by the Flutter team项目地址: https://gitcode.com/GitHub_Trending/pac/packages本指南以 Flutter 团队官方 go_router 包的路由配置为主题系统讲解GoRouter构造器的完整配置方式涵盖路径参数、查询参数、子路由、动态RoutingConfig、ShellRoute嵌套导航与StatefulShellRoute状态化嵌套导航并给出initialLocation与日志调试的配置方法。读完本文你将能够独立搭建从简单页面跳转到复杂多 Tab 应用的路由体系并理解每一层配置背后的源码实现原理。创建 GoRouter最小配置骨架调用 GoRouter 构造函数并提供一个 GoRoute 对象列表即可完成路由配置。这是所有 go_router 应用的起点核心代码如下GoRouter( routes: [ GoRoute( path: /, builder: (context, state) const Page1Screen(), ), GoRoute( path: /page2, builder: (context, state) const Page2Screen(), ), ], );从源码router.dart可以看到GoRouter的工厂构造函数还支持大量可选参数包括redirect、redirectLimit默认 5、refreshListenable、observers、navigatorKey、restorationScopeId等。其中routes列表是应用的路由表不能为空且必须包含一个匹配/的GoRoute否则路由解析将无法定位初始页面。构建完成后通过MaterialApp.router(routerConfig: router)将配置接入应用即可。配置 GoRoute路径模板与 builder配置一个GoRoute必须提供路径模板和 builder 两部分通过path参数指定要处理的路径模板通过builder或pageBuilder参数提供页面构建逻辑GoRoute( path: /users/:userId, builder: (context, state) const UserScreen(), ),builder 与 pageBuilder 的选择builder直接返回 Widget适合大多数普通页面pageBuilder返回Page对象如MaterialPage、CupertinoPage或用于自定义转场动画的CustomTransitionPage适合需要精细控制页面转场、路由动画的场景。从 route.dart 的构造器断言可以看出二者必须至少提供一个若只配置redirect而没有任何 builder则该路由会被视为仅重定向路由redirectOnly。路径模板的额外能力path模板除了支持参数占位符见下文还支持以下特性正则约束参数在参数名后用括号追加正则表达式如path: /users/:userId(\\d)可让/users/42匹配而/users/settings不匹配正则表达式按 DartRegExp解析且不能包含嵌套括号大小写敏感默认caseSensitive: true可显式关闭路由名称通过name为路由命名配合context.namedLocation(name)实现不依赖 URL 字面量的导航。导航到配置的路由使用GoRouter.go()或context.go()即可跳转到已配置的路由。导航机制的整体行为可参见仓库中的 navigation.md 主题文档。参数路径参数与查询参数路径参数Path Parameters在路径段前加:前缀并紧跟唯一名称即可声明路径参数例如:userId。在 builder 回调中通过 GoRouterState 的pathParameters读取参数值GoRoute( path: /users/:userId, builder: (context, state) const UserScreen(id: state.pathParameters[userId]), ),查询参数Query ParametersURL 中?之后的部分为查询字符串可通过GoRouterState.uri.queryParameters读取。例如 URL/users?filteradminsGoRoute( path: /users, builder: (context, state) const UsersScreen(filter: state.uri.queryParameters[filter]), ),GoRouterState.uri是标准Uri对象因此所有Uri的查询参数解析能力多值参数、编码等都可直接复用。仓库中的 path_and_query_parameters.dart 提供了完整的可运行示例。子路由一次匹配多个页面一个匹配到的路由可以对应 Navigator 上的多个页面效果等同于调用push()新页面显示在旧页面之上带有过渡动画并在使用AppBar时自动出现应用内返回按钮。将子路由添加到父路由的routes列表中即可实现页面叠加GoRoute( path: /, builder: (context, state) { return HomeScreen(); }, routes: [ GoRoute( path: details, builder: (context, state) { return DetailsScreen(); }, ), ], )注意子路由的path通常以相对路径书写如detailsgo_router 会自动拼接出完整的/details。子路由是后续嵌套导航与 Shell 路由组合的基础形态。动态 RoutingConfig运行时更新路由表GoRouter创建后路由表并非一成不变。RoutingConfig 提供了一种在路由创建后动态更新GoRoute集合的机制需要配合专用构造器GoRouter.routingConfig使用final ValueNotifierRoutingConfig myRoutingConfig ValueNotifierRoutingConfig( RoutingConfig( routes: RouteBase[GoRoute(path: /, builder: (_, __) HomeScreen())], ), ); final GoRouter router GoRouter.routingConfig(routingConfig: myRoutingConfig);之后直接修改ValueNotifier的 value 即可变更路由myRoutingConfig.value RoutingConfig( routes: RouteBase[ GoRoute(path: /, builder: (_, __) AlternativeHomeScreen()), GoRoute(path: /a-new-route, builder: (_, __) SomeScreen()), ], );值的变更会被GoRouter自动感知源码中通过_routingConfig.addListener(_handleRoutingConfigChanged)注册监听见 router.dart并触发对当前路由的重新解析存储在GoRouter中的RouteMatchList会立即反映最新RoutingConfig的内容。RoutingConfig 支持的其他配置从 router.dart 可以看到RoutingConfig还支持onEnter进入路由前的守卫回调返回Allow放行或Block拦截、redirect顶层重定向回调与redirectLimit重定向最大次数默认 5因此动态配置不仅能改路由也能同步更新守卫与重定向逻辑。仓库中的 routing_config.dart 演示了完整场景点击按钮后通过myConfig.value _generateRoutingConfig()动态新增/new-route路由并可通过router.go(/new-route)立即导航到新路由。嵌套导航使用 ShellRoute 承载常驻 UI某些应用需要将目的地显示在屏幕的一个子区域中例如使用BottomNavigationBar的应用切换目的地时底部导航栏始终停留在屏幕上。此时需要添加额外的 Navigator使用 ShellRoute 并提供一个返回 Widget 的 builderShellRoute( builder: (BuildContext context, GoRouterState state, Widget child) { return Scaffold( body: child, /* ... */ bottomNavigationBar: BottomNavigationBar( /* ... */ ), ); }, routes: RouteBase[ GoRoute( path: details, builder: (BuildContext context, GoRouterState state) { return const DetailsScreen(); }, ), ], ),这里的child是一个专门用于展示匹配子路由的Navigator它被嵌入到你自定义的 shell Widget 中。相比把路由直接挂在根级ShellRoute让深层路由如/a/details只覆盖 shell 内部区域而不会盖住底部导航栏。ShellRoute 实战要点仓库中的 shell_route.dart 是完整的可运行示例展示了三个要点为 shell 分配独立的navigatorKey如_shellNavigatorKey用于区分根 Navigator 与 shell Navigator通过GoRouterState.of(context).uri.path判断当前选中项维护BottomNavigationBar的currentIndex通过parentNavigatorKey: _rootNavigatorKey让某个子路由如/b/details覆盖到根 Navigator 之上——此时它连应用 shell 一起盖住实现全屏详情页的效果。状态化嵌套导航StatefulShellRoute 保持分支状态在基于BottomNavigationBar的嵌套导航中很多应用还要求切换目的地时保留各 Tab 的页面状态滚动位置、已填表单等。此时应使用 StatefulShellRoute 替代ShellRoute。StatefulShellRoute为每个嵌套的 branches即并行的导航树创建独立的Navigator从而支持状态化嵌套导航。构造器StatefulShellRoute.indexedStack提供了基于IndexedStack的分支 Navigator 默认管理实现源码见 route.dart。使用StatefulShellRoute时路由不再直接配置在 shell route 上而是分别配置在每一个分支上branches: StatefulShellBranch[ // The route branch for the first tab of the bottom navigation bar. StatefulShellBranch( navigatorKey: _sectionANavigatorKey, routes: RouteBase[ GoRoute( // The screen to display as the root in the first tab of the // bottom navigation bar. path: /a, builder: (BuildContext context, GoRouterState state) const RootScreen(label: A, detailsPath: /a/details), routes: RouteBase[ // The details screen to display stacked on navigator of the // first tab. This will cover screen A but not the application // shell (bottom navigation bar). GoRoute( path: details, builder: (BuildContext context, GoRouterState state) const DetailsScreen(label: A), ), ], ), ], // To enable preloading of the initial locations of branches, pass // true for the parameter preload (false is default). ),其中StatefulShellBranch的preload参数默认false用于预加载分支的初始位置减少切换时的加载延迟。自定义 shell 与 StatefulNavigationShell与ShellRoute类似StatefulShellRoute.indexedStack也必须提供 builder 来构建真正封装分支导航容器的 shell Widget。该容器由类 StatefulNavigationShell 实现作为 builder 函数的最后一个参数传入StatefulShellRoute.indexedStack( builder: (BuildContext context, GoRouterState state, StatefulNavigationShell navigationShell) { // Return the widget that implements the custom shell (in this case // using a BottomNavigationBar). The StatefulNavigationShell is passed // to be able access the state of the shell and to navigate to other // branches in a stateful way. return ScaffoldWithNavBar(navigationShell: navigationShell); },在自定义 shell Widget 内部StatefulNavigationShell有三个核心用途作为 shell 的 body 直接使用处理分支间的状态化切换提供当前激活分支的索引。典型实现如下override Widget build(BuildContext context) { return Scaffold( // The StatefulNavigationShell from the associated StatefulShellRoute is // directly passed as the body of the Scaffold. body: navigationShell, bottomNavigationBar: BottomNavigationBar( // Here, the items of BottomNavigationBar are hard coded. In a real // world scenario, the items would most likely be generated from the // branches of the shell route, which can be fetched using // navigationShell.route.branches. items: const BottomNavigationBarItem[ BottomNavigationBarItem(icon: Icon(Icons.home), label: Section A), BottomNavigationBarItem(icon: Icon(Icons.work), label: Section B), BottomNavigationBarItem(icon: Icon(Icons.tab), label: Section C), ], currentIndex: navigationShell.currentIndex, // Navigate to the current location of the branch at the provided index // when tapping an item in the BottomNavigationBar. onTap: (int index) navigationShell.goBranch(index), ), ); }其中navigationShell.goBranch(index)在切换 Tab 时导航到对应分支的当前 location同时保留该分支原有导航栈navigationShell.currentIndex提供当前分支索引。完整的可运行示例见 stateful_shell_route.dart仓库配套测试可参考 stateful_shell_route_system_back_test.dart 对分支状态与系统返回键行为的验证。初始位置initialLocation初始位置是应用首次打开、且平台未提供 deep link 时显示的页面。通过GoRouter构造器的initialLocation参数指定GoRouter( initialLocation: /details, /* ... */ );从 router.dart 的实现可以看出_effectiveInitialLocation会优先采用平台默认位置如 deep link仅在未提供时回退到initialLocation这也是overridePlatformDefaultLocation参数存在的意义。若需配合initialExtra使用则必须同时设置initialLocation构造器中有对应断言。日志调试debugLogDiagnostics排查路由匹配问题时可以开启日志输出final _router GoRouter( routes: [/* ... */], debugLogDiagnostics: true, );该参数默认为false。开启后源码中通过setLogging(enabled: debugLogDiagnostics)见 router.dart启用日志基础设施会在控制台输出路由解析、初始位置设置等关键诊断信息帮助快速定位路由未匹配跳转未生效等问题。小结从最小的GoRouterGoRoute配置到路径/查询参数、子路由、动态RoutingConfig、ShellRoute嵌套导航、StatefulShellRoute状态化嵌套导航再到initialLocation与debugLogDiagnostics的调优手段go_router 的配置体系覆盖了绝大多数 Flutter 应用的导航需求。继续深入可参阅仓库中的 navigation.md、deep-linking.md 与 named-routes.md结合 example/lib 下的可运行示例进行实践。【免费下载链接】packagesA collection of useful packages maintained by the Flutter team项目地址: https://gitcode.com/GitHub_Trending/pac/packages创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门