Flutter Web:使用命名路线导航URL

lazihuman
发布于 2020-9-6 10:09
浏览
0收藏

命名路由可以用来在Flutter移动应用内部的页面之间导航,但它们也适用于Flutter Web应用中的URL。这篇文章解释了如何将命名路由添加到您的应用程序中,以及如何自定义它们,以在路由内部进行模式匹配。

 

定义命名路由
通过在MaterialApp类中定义命名路线,可以将其添加到您的应用程序中。MaterialApp.routes 属性包含了一张地图,列出了每个命名的路由及其相关的显示部件。MaterialApp.initialRoute 属性决定了应用程序启动时显示的路由。因此,initialRoute需要在route属性中定义。例如:

MaterialApp(
  initialRoute: '/',
  routes: {
    '/': (context) => HomePage(),
    '/overview': (context) => OverviewPage(),
  },
);



一个好的做法是把命名的路由放在静态变量里, 例如, 放在widgets本身:

class OverviewPage extends StatelessWidget {
  static const String route = '/overview';
}



下一步,重构MaterialApp.routes,将命名的路由定义为静态变量。

MaterialApp(
  initialRoute: HomePage.route,
  routes: {
    HomePage.route: (context) => HomePage(),
    OverviewPage.route: (context) => OverviewPage(),
  },
);



在页面之间导航
要从一个页面导航到另一个页面,只需将命名的路径推到导航器上即可。

RaisedButton(
  onPressed: () {
    Navigator.of(context).pushNamed(OverviewPage.route);
  },
)



在DartPad上可以看到一个完整的交互式示例。如果你自己构建并运行网络应用,你也可以在网络浏览器中输入/#/overview。这样就会将名为overview的路由推送到Navigator,并将你带到OverviewPagewidget,你可以在下面的GIF中看到。

 

 
 

在DartPad上查看完整的交互式示例
动态URL的路由逻辑
您可能需要解决更多复杂的情况,比如在路由中进行模式匹配,以允许动态URL。为了扩展这个例子,假设你在概览页上有许多不同的文章。对于每一篇文章,你希望能够直接通过URL进行导航:

/#/article/a-very-interesting-article
/#/article/newsworthy-news



要为MaterialApp中的所有文章定义命名的路由,并不能很好地扩展。对于这样的动态情况,你需要做一些更自定义的事情。截止到目前,Flutter的稳定通道是在v1.12版本,还没有简单的方法,不过有计划在新的Navigator中增加对更高级路由的支持。

目前你可以使用外部包,比如Fluro包就提供了更高级的路由。它为你提供了路由中的通配符模式匹配,以及URL中查询字符串的解析。可能还有很多其他可用的包,所以请在评论中留下你最喜欢的包的名字。

如果你愿意接受挑战,你也可以通过使用MaterialApp.onGenerateRoute属性来获得动态路由。使用这个属性来编写路由逻辑,当命名的路由不在MaterialApp.routes里面时,就可以使用这个属性。

对于每个路由,定义一个带有 RegEx 模式的 Path。如果命名的路由与该模式匹配,则返回相关的小组件。接下来,定义Path类来支持:

class Path {
  const Path(this.pattern, this.builder);
  
  final String pattern;
  final Widget Function(BuildContext, String) builder;
}



对于概览页和主页路由,它很简单,看起来和你之前的类似。下面的示例创建了一个RegEx模式,该模式匹配一个slug(带破折号的小写字母),用于查找相应的文章。

static List<Path> paths = [
  Path(
    r'^/article/([\w-]+)$',
    (context, match) => Article.getArticlePage(match),
  ),
  Path(
    r'^' + OverviewPage.route,
    (context, match) => OverviewPage(),
  ),
  Path(
    r'^' + HomePage.route,
    (context, match) => HomePage(),
  ),
];



剩下的就是为MaterialApp创建一个onGenerateRoute函数。如果路径列表中定义了当前的命名路由(settings.name),则返回相关的widget。确保在RegEx中传递任何命名匹配(在本例中是slug)。如果没有找到匹配项,就简单地返回null,WidgetsApp.onUnknownRoute被调用来处理这种情况。

static Route<dynamic> onGenerateRoute(RouteSettings settings) {
  for (Path path in paths) {
    final regExpPattern = RegExp(path.pattern);
    if (regExpPattern.hasMatch(settings.name)) {
      final firstMatch = regExpPattern.firstMatch(settings.name);
      final match = (firstMatch.groupCount == 1) ? firstMatch.group(1) : null;
      return MaterialPageRoute<void>(
        builder: (context) => path.builder(context, match),
        settings: settings,
      );
    }
  }
  // If no match is found, [WidgetsApp.onUnknownRoute] handles it.
  return null;
}



确保在MaterialApp类中定义onGenerateRoute函数;你已经用Flutter实现了动态URL,使用了命名的路由!你可以在DartPad上看到一个完整的交互式例子。

 

Flutter Web:使用命名路线导航URL-鸿蒙开发者社区
 

在DartPad上查看完整的交互式示例

 

结束语
无论你是选择为路由编写自己的自定义逻辑,还是简单地使用MaterialApp中存在的路由支持,当使用命名路由时,你都可以通过网络上的Flutter应用默认获得URL支持。实现命名路由还可以确保你将展现逻辑与路由逻辑解耦,从而减少代码重复。 请在评论中告诉我你在你的应用中使用了什么解决方案,是自己编写自定义逻辑还是使用外部包。

作者:Sunbreak
来源:掘金

分类
已于2020-9-6 10:09:36修改
收藏
回复
举报
回复
    相关推荐