Files
2026-09-04 15:22:20 +08:00

87 lines
2.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 【Demo】详情页:参数接收的两种通道
> 源文件:`lib/pages/demo/detail_page.dart` | 分类:路由
> 一句话:构造参数与 ModalRoute arguments 双通道 —— 谁来了用谁,缺谁兜底。
---
## 一、这个 Demo 解决什么问题
同一个详情页,可能被两种方式打开:
- **方式 1**:`push` 构造传参(`DetailPage(name: '张三', age: 18)`);
- **方式 3**:`pushNamed` 命名路由 + arguments(`{'name': '李四', 'age': 25}`)。
页面要**同时兼容两种入口**:优先用 arguments 里的值,没有就用构造参数兜底。
---
## 二、怎么运行 / 演示内容
```dart
runApp(const RouterApp());
```
首页分别用方式 1 / 方式 3 跳进来,观察两种取参路径的效果。
---
## 三、核心知识点(新手向)
### 1. 构造参数(类型安全)
```dart
class DetailPage extends StatelessWidget {
const DetailPage({super.key, this.name = '默认', this.age = 0});
final String name;
final int age;
...
}
```
- 带默认值 → 不传参也能打开,不会崩;
- 类型安全:传错类型编译期报错。
### 2. 命名路由 arguments(运行期 Map)
```dart
final args = ModalRoute.of(context)?.settings.arguments;
final argMap = args is Map<String, dynamic> ? args : null;
```
- `ModalRoute.of(context)` 拿到当前路由 → `.settings.arguments` 取出 pushNamed 传的参数;
- arguments 是 dynamic,**必须判空强转**:
- 不是 Map(或没传)→ `argMap` 为 null;
- `argMap?['name']` 取不到时用 `?? name` 回退构造参数。
### 3. 双通道合并取值(本页精髓)
```dart
Text('姓名:${argMap?['name'] ?? name}'),
Text('年龄:${argMap?['age'] ?? age}'),
```
"arguments 优先,构造参数兜底"——两种入口都兼容,缺参不崩。
---
## 四、关键代码剖析
```dart
// 手动 pop(AppBar 的返回箭头也是 pop,效果一样)
OutlinedButton(
onPressed: () => Navigator.pop(context),
child: const Text('返回上一页'),
)
```
---
## 五、踩坑记录
1. `arguments` 是 dynamic,**直接用会崩**(`args['name']` 对非 Map 类型运行期报错)——先 `is Map` 判断;
2. `ModalRoute.of(context)?.settings.arguments` 有 `?`,路由可能为 null;
3. 构造参数给默认值,保证"零参数也能打开页面"(debug 直达页面时很有用);
4. 命名路由注册在 [router_demo.md](router_demo.md) 的 routes 表里。
---
## 六、扩展思考
- 选择器页 pop 带值见 [picker_page.md](picker_page.md);
- 参数多了建议封装成强类型对象(`class DetailArgs`),避免 Map 满天飞;
- 真实项目(go_router)用 `GoRoute` 的 `arguments` 或 `extra` 传对象,原理一致。