[译]Flutter Favorite之路由包go_router - 基础篇

本文详细介绍了Flutter库go_router的使用,包括声明式路由、路由状态、初始化、错误处理、深度链接、导航、参数传递、子路由、重定向、命名式路由、URL路径策略等内容,旨在降低路由和导航复杂度,支持跨平台操作。通过实例和代码示例,阐述了go_router如何简化页面间导航和处理路由事件。
摘要由CSDN通过智能技术生成

go_router

欢迎来到 go_router !

MaterialApp.router 指定的 Flutter Router API 需要 RouterDelegate 类和 RouteInformationParser 类的实现。

这两个实现本身意味着第三种类型的定义,该类型保有驱动创建 Navigator 的应用状态。 可以阅读 Medium 上一篇关于这些需求的优秀博客(需要借助一些工具访问)。这种责任分离允许 Flutter 开发者来实现多种路由和导航策略,包括深度链接和动态链接,但是代价是复杂度

go_router 包的目的是使用声明式路由来降低复杂度,无论面向的是哪个目标平台(移动端、Web、桌面端)。在 Android、iOS 和 Web 上处理深度链接和动态链接,以及多个其它与导航关联的场景,同时仍然(有望)提供一个简单易用的开发者体验。

开始

go_router | Flutter Package (flutter-io.cn)

官网提供的视频在油管上,有兴趣的同学可前往观看。

声明式路由

go_router 由 GoRouter 构造器中指定的路由集合部分来管理。

class App extends StatelessWidget {
  ...
  final _router = GoRouter(
    routes: [
      GoRoute(
        path: '/',
        builder: (context, state) => const Page1Screen(),
      ),
      GoRoute(
        path: '/page2',
        builder: (context, state) => const Page2Screen(),
      ),
    ],
  );
} 

这种情况下,定义了两个路由,每个路由 path 都会匹配用户导航的位置。只有单个路由会被匹配,具体来说,就是某个路由的 path 会匹配整个位置(所以路由的列出顺序无关紧要)。 path 匹配时忽略大小写,即使参数会保留大小写。

除了 path 之外,每个路由会代表性地带有一个 builder 函数,该函数负责构建用来占据应用整个屏幕的组件。页面间会使用默认转换 ,取决于添加到组件树顶部的应用类型。例如,使用 MaterialApp 会让 go_router 使用 MaterialPage 的转换。

路由状态

如果在上面代码片段中不使用时,builder 函数会接收一个 state 对象,该对象是 GoRouterState 的一个实例,包含一些有用的信息:

GoRouterState

属性 描述 示例 1 示例 2
location 完整路由的位置,包含查询参数 /login?from=/family/f2 /family/f2/person/p1
subloc 子路由的位置,不包含查询参数 /login /family/f2
name 路由名称 login family
path 路由路径 /login family/:fid
fullpath 该子路由的完整路径 /login /family/:fid
params 从位置中提取的参数 {} {'fid': 'f2'}
queryParams 位置末尾的可选参数 {'from': '/family/f1'} {}
extra 可选的对象参数 null null
error 如果有 Exception('404') ,该属性为子路由关联的 Exception (异常)
pageKey 该子路由的唯一键 ValueKey('/login') ValueKey('/family/:fid')

state 对象用于为参数化路由传递参数和重定向。不是每次都要设置所有的 state 参数。通常, GoRouterState 定义一个 GoRouterState 实例可能的当前 state 的超集。例如,仅当有错误时会设置 error 参数。

初始化

用路由列表可以创建 GoRouter 的实例,它自身提供了调用 MaterialApp.router 构造器(或CupertinoApp.router 构造器)所需的对象:

class App extends StatelessWidget {
  App({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) => MaterialApp.router(
        routeInformationParser: _router.routeInformationParser,
        routerDelegate: _router.routerDelegate,
      );

  final _router = GoRouter(routes: ...);
} 

使用合适位置的路由,你的应用现在可以在页面间导航navigate between pages了。

错误处理

默认情况下,go_router 会为 MaterialAppMaterialApp 转到默认的错误界面,即使没有为两者设置默认的错误界面。也可以通过设置 GoRoutererrorBuilder 参数来替换掉默认的错误界面。

class App extends StatelessWidget {
  ...
  final _router = GoRouter(
    ...
    errorBuilder: (context, state) => ErrorScreen(state.error),
  );
} 

错误界面,无论你或 go_router 有没有提供,都会在以下情况时使用:位置没有匹配路由(404),一个位置匹配了多个的路由,或者某个 builder 函数抛出了异常。

深度链接

Flutter 把 “深度链接” 定义为 打开一个 URL 来展示应用中的对应页面。任意作为 GoRoute 列出的内容都可以在 Android、iOS、Web 平台通过深度链接(打开)。对于支持 Web 开箱即用,当然是通过地址栏。但是在 Android 和 iOS 上需要另外的配置,在 Flutter docs 文档中有相关描述。

导航

在页面间导航,使用 GoRouter.go 方法:

// 使用 GoRouter 导航
onTap: () => GoRouter.of(context).go('/page2') 

go_router 还提供了一个使用 Dart 扩展方法的简化的导航:

// 使用 GoRouter 导航更容易
onTap: () => context.go('/page2') 

简化的版本直接映射到完整版本,所以也可以使用。 如果你对此好奇,只是调用 context.go(...) 就能发生魔法,这就是 go_router 的来历。

如果想用 Link 组件来导航,那也是有效的:

Link(
  uri: Uri.parse('/page2'),
  builder: (context, followLink) => TextButton(
    onPressed: followLink,
    child: const Text('Go to page 2'),
  ),
), 

如果为 Link 组件提供一个带 scheme (页面内跳转协议) 的 URL,例如:https://flutter.dev,它会在浏览器中载入这个 URL。否则,它会在应用内使用内置的导航系统打开链接。

也可以导航到一个命名式路由 [中文] 。

页面入栈

除了 go 方法之外, go_router 还提供了 push 方法。 gopush 都可用来构建页面栈,但是方式不同。 go 方法通过使用 子路由 把单个位置转换为栈中的多个页面。

push 方法把单个页面推入到现有页面的栈中,这意味着可以编程式来构建栈,而不是声明式。当 push 方法通过子路由匹配整个栈时,它会从栈中选择最顶层的页面,并推入到栈中。

你也可以 push 一个命名式路由 [中文] 。

弹出页面

如果想要从栈中弹出一个页面,可以使用 pop 方法。这个方法只是简单地调用 Navigator.pop。关于使用 NavigatorGoRouter 集成的注意事项的更多信息,参考导航集成

初始化位置

如果想为路由设置一个初始化位置,可以设置 GoRouter 构造器的 initialLocation 参数:

final _router = GoRouter(
  routes: ...,
  initialLocation: '/page2',
); 

如果应用是通过深度链接 [中文]启动的,提供给 initialLocation 的值会被忽略。

当前位置

如果想知道当前位置,使用 GoRouter.location 属性。

如果想知道现在位置改变的时间点,由手动导航、或深度链接、或用户点击返回按钮的弹出,GoRouter 本身也是 ChangeNotifier ,这意味着可以调用 addListener 用来在现在位置改变时接收通知,手动或通过用 Flutter 为 ChangeNotifier 对象构建组件 AnimatedBuilder,命名不是很直观。

class RouterLocationView extends StatelessWidget {
  const RouterLocationView({Key? key}) : super(key: key);

  @
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当使用 Flutter 的 go_router 进行进阶使用时,您可以探索以下功能和技巧: 1. 命名路由:除了使用路径来导航页面,go_router 还支持命名路由,通过给每个路由规则指定一个唯一的名称,可以更方便地进行页面跳转。例如: ```dart final routes = [ GoRoute( path: '/', pageBuilder: (context, state) => HomePage(), name: 'home', ), GoRoute( path: '/details/:id', pageBuilder: (context, state) => DetailsPage(id: state.params['id']), name: 'details', ), ]; ``` 然后,您可以通过名称进行页面跳转: ```dart GoRouter.of(context).goNamed('details', params: {'id': '123'}); ``` 2. 参数传递:go_router 允许您在页面之间传递参数。在路由规则中,可以定义参数占位符,然后在页面构建器中获取这些参数并使用它们。例如: ```dart final routes = [ GoRoute( path: '/details/:id', pageBuilder: (context, state) => DetailsPage(id: state.params['id']), ), ]; ``` 在 DetailsPage 中可以通过 `widget.id` 访问传递的参数。 3. 路由拦截和重定向:go_router 允许您在路由跳转之前进行拦截和处理。您可以使用 `beforeEnter` 方法来拦截特定的路由,并根据需要执行操作,例如权限验证、参数校验等。还可以使用 `redirectTo` 方法来重定向到其他路由。例如: ```dart final routes = [ GoRoute( path: '/details/:id', pageBuilder: (context, state) => DetailsPage(id: state.params['id']), beforeEnter: (context, state) { // 进行权限验证或其他操作 if (!isLoggedIn) { return redirectTo('/login'); } return null; }, ), ]; ``` 4. 页面切换动画:go_router 支持自定义页面切换动画,您可以为每个路由规则定义不同的动画效果。使用 `transitionDuration` 和 `transitionBuilder` 属性来自定义页面切换动画。例如: ```dart final routes = [ GoRoute( path: '/', pageBuilder: (context, state) => HomePage(), transitionDuration: Duration(milliseconds: 500), transitionBuilder: (context, animation, secondaryAnimation, child) { return FadeTransition(opacity: animation, child: child); }, ), ]; ``` 在上述示例中,我们使用了一个渐变的动画效果。 这些是 go_router 的一些进阶使用方法,您可以根据您的实际需求来灵活使用它们。请参考 go_router 的官方文档以获取更多详细信息和示例代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值