[Flutter翻译]Beamer v1.0.0发布了! 什么是新的和如何迁移

2021-12-07 12:59:22 浏览数 (1)

在pub.dev上运行了近一年,经过许多个人和公司的测试和使用,long......

Beamer v1.0.0发布了! 什么是新的和如何迁移

在pub.dev上运行了近一年,经过许多个人和公司的测试和使用,期待已久的_v1.0.0_终于发布了_。

目录

  • 简介
  • v0.14.1之后的新内容
  • 如何迁移
  • 最后的想法

简介

Beamer是一个适用于所有平台的路由包,它可以让你使用RouterNavigator的Pages API(又称 "Navigator 2.0")在受保护的页面堆栈和URL中导航。

如果你不熟悉这些导航概念,Learning Flutter's new navigation and routing system是一篇可以开始阅读的好文章。本文的其余部分假定熟悉上述概念,并对Beamer有一定的了解,其README可以在下面的链接中阅读。

beamer | Flutter包 处理您的应用程序在所有平台上的路由,使其与浏览器的URL栏同步等等。Beamer使用的动力是... pub.dev/packages/be…

有2个主要想法指导Beamer的诞生。

  • 使Router API的使用更容易,特别是对初学者而言
  • 将创建页面堆栈的责任分离出来,供中级和高级使用。

第一点是通过对 "RouterDelegate "和 "RouteInformationParser "的默认实现来解决的,即 "BeamerDelegate "和 "BeamerParser"。两者都可以采取各种参数进行定制。拥有命名的路线在一开始就显示出是一个需要的功能,所以有一个RoutesLocationBuilder,可以用熟悉的routes地图进行配置。设置完成后,导航可以通过Beamer.of(context).beamToNamed('/my/page/2')这样的方式完成,这使得从Navigator.of(context).pushNamed('/my-page')的过渡对新人来说非常自然。

第二点是由一个BeamLocation的概念完成的,它负责根据它的状态来决定BeamerDelegate在(重新)构建时应该把哪些页面放入Navigator.pages。这里的想法是为应用程序中不同的 "区域/地点/世界 "定义不同的BeamLocation。例如,我们可以有BooksBeamLocation来处理一个堆栈中所有与书籍相关的页面组合,还有ArticlesBeamLocation来处理一个堆栈中所有与文章相关的页面。当需要建立一个包含10多个屏幕的应用程序时,这种方法的好处很快就可以看到,这些屏幕被组织在几个 "上下文不同 "的页面堆栈中。

当定义你的 "BeamLocation "时,用于它的 "state "可以是默认的 "BeamState"(持有对决定如何建立一个页面堆栈很重要的各种路由参数)或一个完全自定义的状态对象,甚至(但不是必须的)一个 "ChangeNotifier"。当使用一个自定义的ChangeNotifier作为BeamLocation的状态时,可以完成纯粹的声明式导航。然而,即使使用ChangeNotifier状态,人们也能同样地进行强制性的导航。Beamer并不偏爱其中的一种,它对两者的处理都是类似的。下一个目标可能是使默认的BeamState成为ChangeNotifier,但这是下一篇文章的主题 :)

每个导航动作后发生的流程可以在下图中看到。

v0.14.1之后的新内容

一个完整的变化日志可以看到在pub.dev,所以我们会去看每个突破性变化背后的原因和一些值得一提的地方。

BeamState的变化

  1. 它现在与RouteInformationSerializable混合,这是一个在Beamer中定义的混合元素,每个BeamLocation的状态都必须与之混合。
  2. pathBlueprintSegments更名为pathPatternSegments

BeamerDelegate的变化

  1. 你们中的一些人可能会注意到,特别是如果直接使用Beamer.of(context).updateBeamerDelegate也存储其 "状态"。在这之前,这是一个叫做state'的BeamState',但这感觉不太对。现在这是一个叫做 "configuration "的RouteInformation,与RouterDelegate中的名称相同。
  2. 所有的波束参数,如transitionDelegate', beamBackOnPop'和其他的都被提取到一个`BeamParameters'对象中。这不是一个突破性的变化,因为这些参数在波束函数中保持不变,但这是一个变化,与上述变化一起影响了以下变化
  3. locationBuilder现在接受RouteInformationBeamParameters而不是BeamState。这是上述变化的自然结果,但也是一个改进,因为它提供了将光束参数保存到历史中的能力,这在以前是不可能的。
  4. beamStateHistorybeamLocationHistory被替换为beamingHistory,它是一个List<BeamLocation>,每个BeamLocation都有history,是List<HistoryElement>,其中HistoryElement持有RouteInformationBeamParameters。这句话很快就升级了,但现在我们有一个非常稳定和结构良好的光束历史。
  5. listener被重新命名为routeListener,并增加了一个新的buildListener。这样,我们就可以同时监听传入的路由(在构建之前)和构建时(在那里我们也可以访问页面)。

BeamLocation的变化

  1. 由于 "BeamerDelegate "的变化,构造函数现在需要可选的 "路由信息 "和 "BeamParameters"。
  2. "状态 "的 "T "型现在必须与 "RouteInformationSerializable "混合,在扩展 "BeamLocation "时,必须为状态指定一个通用类型,即使使用默认的 "BeamState "也是如此。
  3. pathBlueprints'更名为pathPatterns',是一个List<Pattern>

关于SimpleLocationBuilder的变化

  1. 重命名为RoutesLocationBuilder。这是由于Navigator 2.0 API Usability Research的讨论
  2. routes的值现在也接受Object? data参数。

BeamPage上的变化

  1. pageRouteBuilder被更通用的routeBuilder所取代。
  2. 我们现在有了一个const构造函数
  3. 增加了一个静态的routePop',可以代替默认的pathSegmentPop'用于`onPopPage'。

BeamGuard的变化

  1. pathBlueprints改名为pathPatterns
    1. beamTobeamToNamed现在也接收origintarget,它们是被传送的地方和被传送到的地方的BeamLocation(这是被保护的)。

对例子的补充

  • Guard riverpod example
  • Firebase核心实例
  • Firebase auth example
  • ChangeNotifier自定义状态示例

如何迁移

虽然有很多变化,但迁移是非常直接的。我们将通过2种迁移方案;当使用SimpleLocationBuilder和使用自定义BeamLocation时。

简单定位器生成器

正如我们上面提到的,SimpleLocationBuilder被重新命名为RoutesLocationBuilder。这就完成了50%的迁移,我们只需要在routes中添加data参数,但是让我们写一些代码。

以前我们有这样的东西

代码语言:javascript复制
final routerDelegate = BeamerDelegate(
  locationBuilder: SimpleLocationBuilder(
    routes: {
      '/': (context, state) => MyWidget(),
      '/another': (context, state) => MyAnotherWidget(),
    },
  ),
  // other properties...
);
复制代码

迁移后,我们应该有这样的东西

代码语言:javascript复制
final routerDelegate = BeamerDelegate(
  locationBuilder: RoutesLocationBuilder(
    routes: {
      '/': (context, state, data) => MyWidget(),
      '/another': (context, state, data) => MyAnotherWidget(),
    },
  ),
  // other properties...
);
复制代码

自定义BeamLocation

如前所述,我们必须将pathBlueprints'重命名为pathPatterns',并在扩展BeamLocation'时放入一个具体的state'类型。

在0.14.1版本中,我们可以有

代码语言:javascript复制
class BooksLocation extends BeamLocation {
  @override
  List<Pattern> get pathBlueprints => ['/', '/books'];

  @override
  List<BeamPage> buildPages(BuildContext context, BeamState state) {
    return [
      BeamPage(
        key: const ValueKey('home'),
        child: const HomeScreen(),
      ),
      if (state.uri.pathSegments.contains('books'))
        BeamPage(
          key: const ValueKey('books'),
          child: const BooksScreen(),
        ),
    ];
  }
}
复制代码

现在我们有

代码语言:javascript复制
class BooksLocation extends BeamLocation<BeamState> {
  @override
  List<Pattern> get pathPatterns => ['/', '/books'];

  @override
  List<BeamPage> buildPages(BuildContext context, BeamState state) {
    return [
      const BeamPage(
        key: ValueKey('home'),
        child: HomeScreen(),
      ),
      if (state.uri.pathSegments.contains('books'))
        const BeamPage(
          key: ValueKey('books'),
          child: BooksScreen(),
        ),
    ];
  }
}
复制代码

注意我们现在可以使用const构造函数的BeamPage,而不需要在所有属性上使用它(如果我们用prefer_const_constructors林特规则开发)。

杂项

访问currentBeamLocation.state

现在,state类型不能被自动推断(即使它是一个默认的BeamState),所以我们需要手动铸造它,以便能够访问其类型的所需属性。

之前我们可以做

代码语言:javascript复制
final beamState = Beamer.of(context).currentBeamLocation.state;
final bookId = beamState.pathParameters['bookId'];
复制代码

现在我们必须

代码语言:javascript复制
final beamState = Beamer.of(context).currentBeamLocation.state as BeamState;
final bookId = beamState.pathParameters['bookId'];
复制代码

BeamGuard

如在BeamLocation中,pathBlueprints被重命名为pathPatternsbeamTo/beamToNamed得到了两个参数。

以前我们有

代码语言:javascript复制
BeamGuard(
  pathBlueprints: ['/login'],
  guardNonMatching: true,
  check: (context, location) => context.isUserAuthenticated(),
  beamToNamed: '/login',
)
复制代码

现在我们有这样的参数

代码语言:javascript复制
BeamGuard(
  pathPatterns: ['/login'],
  guardNonMatching: true,
  check: (context, location) => context.isUserAuthenticated(),
  beamToNamed: (origin, target) => '/login',
)
复制代码

最后的想法

我希望这篇文章对已经在使用Beamer的人有帮助,甚至对正在考虑开始新的导航概念的人有帮助。这对我来说肯定是(而且是)很有趣的,我计划在将来写更多关于它的文章。

欢迎访问Beamer的GitHub仓库或Discord服务器,以进一步讨论和了解你可能遇到的问题。

0 人点赞