GoRouter 多参数传递指南
在 Flutter 中,当从传统的 Navigator
导航切换到 go_router
时,如何传递多个参数到其他页面是一个常见问题。本文将详细介绍在 go_router 中传递多个参数的几种最佳方法。
问题背景
在传统 Flutter 导航中,我们可以直接传递多个参数:
dart
Navigator.of(context).push(MaterialPageRoute(
builder: (_) => CatalogFilterPage(
list: list,
bloc: bloc,
)));
但在 go_router 中,我们需要使用不同的方法来处理参数传递。
版本兼容性注意
go_router 在不同版本中有重大变更:
- 低于 7.0.0: 使用
params
和queryParams
- 7.0.0 到 10.0.0: 使用
pathParameters
和queryParameters
- 10.0.0 及以上: 使用
pathParameters
和uri.queryParameters
解决方案
1. 使用 pathParameters(路径参数)
当你知道参数的数量和名称时,可以使用路径参数。
定义路由
dart
GoRoute(
path: '/sample/:id1/:id2', // 在路径中定义参数
name: 'sample',
builder: (context, state) => SampleWidget(
id1: state.pathParameters['id1'],
id2: state.pathParameters['id2'],
),
),
导航到目标页面
dart
ElevatedButton(
onPressed: () {
var param1 = "param1";
var param2 = "param2";
context.goNamed("sample", pathParameters: {
'id1': param1,
'id2': param2
});
},
child: const Text("Navigate"),
),
接收参数
dart
class SampleWidget extends StatelessWidget {
final String? id1;
final String? id2;
const SampleWidget({super.key, this.id1, this.id2});
@override
Widget build(BuildContext context) {
// 使用参数...
}
}
2. 使用 queryParameters(查询参数)
当参数数量不确定或需要传递可选参数时,使用查询参数。
定义路由
dart
GoRoute(
name: "sample",
path: "/sample",
builder: (context, state) => SampleWidget(
id1: state.uri.queryParameters['id1'],
id2: state.uri.queryParameters['id2'],
),
)
导航到目标页面
dart
ElevatedButton(
onPressed: () {
var param1 = "param1";
var param2 = "param2";
// 方法1: 使用 goNamed
context.goNamed("sample", queryParameters: {
'id1': param1,
'id2': param2
});
// 方法2: 使用 go 和 URL 参数
// context.go("/sample?id1=$param1&id2=$param2");
},
child: const Text("Navigate"),
),
3. 使用 extra(传递对象)
当需要传递复杂对象时,可以使用 extra
参数。
定义路由
dart
GoRoute(
path: '/item-screen',
builder: (context, state) {
MenuModels models = state.extra as MenuModels;
return ItemScreen(menuModels: models);
},
),
传递单个对象
dart
context.push(
'/item-screen',
extra: widget.menuModels,
);
传递多个对象
dart
context.goNamed(
'path-name',
extra: {
'par1': object1,
'par2': object2,
},
);
// 在路由中接收
GoRoute(
path: '/path',
name: 'path-name',
builder: (context, state) {
Map<String, dynamic> extra = state.extra as Map<String, dynamic>;
return ScreenName(
par1: extra['par1'],
par2: extra['par2'],
);
},
),
方法对比
选择正确的参数传递方式
方法 | 适用场景 | 优点 | 缺点 |
---|---|---|---|
pathParameters | 参数数量固定且已知 | 类型安全,URL 清晰 | 参数变化时需要修改路径 |
queryParameters | 参数可选或数量可变 | 灵活,无需修改路径 | 需要手动解析参数 |
extra | 传递复杂对象 | 直接传递对象,无需序列化 | 不支持深度链接 |
最佳实践
- 简单数据:使用
pathParameters
或queryParameters
- 复杂对象:使用
extra
参数 - 保持一致性:在项目中统一参数传递方式
- 错误处理:总是对类型转换进行验证
dart
// 安全的类型转换示例
builder: (context, state) {
final extra = state.extra;
if (extra is Map<String, dynamic>) {
return ScreenName(
par1: extra['par1'] as YourType,
par2: extra['par2'] as AnotherType,
);
} else {
// 处理错误情况
return ErrorWidget();
}
},
总结
go_router 提供了多种传递参数的方法,每种方法都有其适用场景。根据你的具体需求选择合适的方法:
- 使用
pathParameters
传递固定参数 - 使用
queryParameters
传递可选参数 - 使用
extra
传递复杂对象
正确使用这些方法可以让你的路由导航更加清晰和可维护。