Flutter路由管理插件route_tree的使用
Flutter路由管理插件route_tree的使用
RouteTree
RouteTree 是一个用于解析 URI 路径的通用库。
RouteTree 是一个通用路由库,它使得基于 URI 的路径段实现路由逻辑变得非常简单。这通过嵌套 Segment
节点来构建一个树状结构,类似于你在 Flutter 应用程序中看到的 Widget
树。
快速示例
final router = Segment.root<String>(
create: (context) => "home",
createError: (context) => "Error!",
children: [
Segment.path(
name: "first_path",
create: (context) => "routed to first_path",
),
Segment.path(
name: "second_path",
create: (context) => "routed to second_path",
children: [
Segment.param(
parser: const UintParser("id"),
create: (context) => "routed to /second_path/${context["id"]}",
),
],
),
],
);
assert(router.route(Uri.parse("/second_path/12")) == "routed to second_path/12");
注意模板参数,该参数表示 RootSegment.route
将返回的数据类型。这使得 route_tree 非常灵活。
它如何工作
这个库的基本构建块是 Segments
、SegmentParsers
和 ParseContext
。
Segments
Segments 是 route_tree 中的 Widget。每个 Segment
代表一个可能的路径段,可以作为路由的一部分。由于它是模板化的,因此可以用多种方式使用,例如在 Flutter 应用程序中进行路由或在后端选择正确的函数来处理传入的 HTTP 请求。抽象类 Segment
包含几个工厂构造方法,以简化查找正确的 Segment
。
RootSegment 或 Segment.root
任何 route_tree 的根节点。
定义了 “/” 路由、根错误处理器以及一组可以用来断言路由树某些属性的 SegmentVerifier
。
默认情况下,RootSegments 包含 findConflictingParamKeys
,如果路由树包含重复的参数键(如 /users/{id}/edit/{id}
),则会返回错误。
/// 匹配 "/"
final router = Segment.root<String>(
create: (context) => "home",
createError: (context) => "root error",
children: [
...
],
);
PathSegment 或 Segment.path
你最常使用的 Segment。它定义了一个简单的文字路径段。内部包含在具有 LiteralParser
的 Segment
的子节点(默认只适用于 PathSegment
)被包含在一个 Map<String, PathSegment>
中,以便于快速查找相应的路径段。
Segment.root<String>(
...
children: [
/// 匹配 "/about"
Segment.path(
name: "about",
create: (context) => "about",
),
/// 匹配 "/settings/*",但不匹配 "/settings" 本身,因为 [create] 为 null
Segment.path(
name: "settings",
children: [
/// 匹配 "/settings/privacy"
Segment.path(
name: "privacy",
create: (context) => "privacy",
),
],
),
],
);
RegExpPathSegment 或 Segment.regExpPath
用于定义一个或多个路径,这些路径应该由一个 Segment
使用正则表达式匹配。
Segment.root<String>(
...
children: [
/// 匹配任何由字母组成的路径段
Segment.regExpPath(
regExp: RegExp(r"[a-zA-Z]+"),
create: (context) => "letter path",
),
],
);
ParamSegment 或 Segment.param
用于定义路径参数。如果 URI 的段匹配,则将匹配值添加到 ParseContext
中,可以从 ParseContext
中查询该值。
Segment.root<String>(
create: (context) => "home",
createError: (context) => "error!",
children: [
/// 匹配 "/users/*",因为 [create] 为 null
Segment.path(
name: "users",
children: [
/// 匹配 "/users/{id}",其中 {id} 是由 [UintParser] 定义的任何非负整数。
Segment.param(
parser: const UintParser("id"),
create: (context) => context["id"] as String,
),
],
),
],
);
RegExpParamSegment 或 Segment.regExpParam
考虑像 Twitter 这样的 URL,例如 https://twitter.com/{name}
,其中 name
可以是任何单词,而一个假设的 Twitter 客户端显然不能硬编码所有可能的名字。这就是这个 Segment
发挥作用的地方。它可以用来定义一个路径参数,该参数匹配提供的正则表达式,并将其注入到 ParseContext
中,可以从 ParseContext
中查询该值。
final router = Segment.root<String>(
create: (context) => "home",
createError: (context) => "error!",
children: [
/// 匹配任何由字母组成的路径段
Segment.regExpParam(
parser: RegExpParamParser.forward(
key: "name",
regExp: RegExp(r"\w+"),
),
create: (context) => context["name"] as String,
),
],
);
assert(router.route(Uri.parse("/flutterdev")) == "flutterdev");
SegmentParsers
实际的解析逻辑,用于查找正确的段,委托给 SegmentParser
的实例。预定义的解析器包括:
SegmentParser.withFunction
,它接受一个Parser
函数,可用于快速定义自定义SegmentParses
LiteralParser
,主要用于PathSegment
(& Segment.path
),并按文字匹配路径段RegExpParser
,根据正则表达式匹配路径段ParamParser
,是SegmentParser
的子类,也是注入匹配项到ParseContext
的解析器基类ParamParser.withFunction
,可用于快速定义自定义ParamParsers
RegExpParamParser
,类似于RegExpParser
,但也会将成功的匹配项注入到ParseContext
IntParser
和UintParser
,分别匹配整数和非负整数。后者对id
路径参数很有用。
ParseContext
ParseContext
包含初始 URI 以及当前路由中的任何路径参数。当路径匹配时调用的 create
函数会传递该上下文。
示例代码
import 'package:route_tree/route_tree.dart';
void main() {
final router = Segment.root<String>(
create: (context) => 'home',
createError: (context) => 'Error!',
children: [
Segment.path(
name: 'first_path',
create: (context) => 'routed to first_path',
),
Segment.path(
name: 'second_path',
create: (context) => 'routed to second_path',
children: [
Segment.param(
parser: const UintParser('id'),
create: (context) => 'routed to /second_path/${context['id']}',
),
],
),
],
);
assert(
router.route(Uri.parse('/second_path/12')) == 'routed to second_path/12');
}
更多关于Flutter路由管理插件route_tree的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter路由管理插件route_tree的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,关于Flutter中的路由管理插件route_tree
的使用,这里提供一个简单的代码案例来展示其基本功能。route_tree
是一个用于Flutter的路由管理库,它提供了一种声明式的方式来定义应用中的路由结构。
首先,确保你的pubspec.yaml
文件中已经添加了route_tree
依赖:
dependencies:
flutter:
sdk: flutter
route_tree: ^最新版本号 # 替换为实际最新版本号
然后运行flutter pub get
来安装依赖。
以下是一个使用route_tree
的简单示例:
main.dart
import 'package:flutter/material.dart';
import 'package:route_tree/route_tree.dart';
import 'home_page.dart';
import 'details_page.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp.router(
routeInformationParser: RouteTreeParser(),
routerDelegate: RootRouterDelegate(
// 定义路由树
child: RouteTreeNode(
path: '/',
builder: (_, __) => HomePage(),
children: [
RouteTreeNode(
path: 'details',
builder: (_, args) => DetailsPage(id: args['id'] as int),
),
],
),
),
);
}
}
home_page.dart
import 'package:flutter/material.dart';
import 'package:route_tree/route_tree.dart';
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Home Page')),
body: Center(
child: ElevatedButton(
onPressed: () {
// 导航到详情页面,并传递参数
context.push('/details', arguments: {'id': 123});
},
child: Text('Go to Details'),
),
),
);
}
}
details_page.dart
import 'package:flutter/material.dart';
class DetailsPage extends StatelessWidget {
final int id;
DetailsPage({required this.id});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Details Page')),
body: Center(
child: Text('Details for ID: $id'),
),
);
}
}
解释
-
main.dart:这是应用的入口文件。我们使用了
MaterialApp.router
来配置路由,并指定了routeInformationParser
和routerDelegate
。RootRouterDelegate
是route_tree
提供的一个委托,用于处理路由树的逻辑。 -
RouteTreeNode:在
RootRouterDelegate
中,我们定义了一个路由树。根节点是HomePage
,它有一个子节点DetailsPage
。子节点的路径是/details
,并且可以通过arguments
接收参数。 -
home_page.dart:
HomePage
包含一个按钮,点击按钮时会触发导航到详情页面,并传递一个参数id
。 -
details_page.dart:
DetailsPage
接收一个id
参数,并在页面上显示。
这个简单的示例展示了如何使用route_tree
进行路由管理,并通过路径和参数在页面之间进行导航。你可以根据需要扩展这个示例,添加更多的页面和复杂的路由结构。