Files
App.K12.Student.Miniapp_Flu…/docs/demos/picker_page.md
T
2026-09-04 15:22:20 +08:00

108 lines
3.9 KiB
Markdown
Raw 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】选择器页:pop 带值返回
> 源文件:`lib/pages/demo/picker_page.dart` | 分类:路由
> 一句话:路由返回值的经典用法 —— 点"男/女",把结果带回上一个页面。
---
## 一、这个 Demo 解决什么问题
"选性别"这类**选择器页**:打开 → 点选项 → 关闭并把结果带回调用页。
本页是 34 行的最小完整例子,专门讲清 **pop 的第二个参数**。
```
首页 await push 选择器页 → 用户点"男" → Navigator.pop(context, '男')
→ 首页的 await 拿到 '男' → 弹 SnackBar 展示
```
> 对照 Vue:等价于 `this.$emit('select', '男')` 后关闭弹窗——Flutter 里返回值走 `pop` 的第二个参数。
---
## 二、怎么运行 / 演示内容
```dart
runApp(const RouterApp()); // 从首页"方式 2"按钮进入本页
```
首页点"选择性别" → 本页两个选项(男/女)→ 点任一 → 回到首页并弹 SnackBar 显示结果;
按系统返回键(不选)→ 首页提示"未选择"。
---
## 三、核心知识点(新手向)
### 1. pop 的第二个参数就是"返回值"
```dart
ListTile(
title: const Text('男'),
onTap: () => Navigator.pop(context, '男'), // 第二个参数:返回给上一页的值
),
```
### 2. 与 push 侧配对使用
```dart
// 接收侧(router_home_page.dart)
final result = await Navigator.push<String>(context, MaterialPageRoute(...));
// 返回侧(本页)
Navigator.pop(context, '男');
```
- `pop(context, value)` 的值类型与 `push<String>` 的泛型对应;
- **用户没选(系统返回键 / 手势返回)→ 没调 pop 带值 → 接收侧拿到 `null`**,所以接收侧要 `?? '未选择'` 兜底。
### 3. pop 之后,页面就销毁了
`Navigator.pop` 会把当前路由出栈并销毁。所以**pop 之后再不能用本页的 context**(页面没了)——这也是"await 之后判 mounted"问题的另一面。
---
## 四、关键代码剖析
```dart
class PickerPage extends StatelessWidget {
const PickerPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('选择性别')),
body: Column(
children: [
ListTile(
leading: const Icon(Icons.male, color: Color(0xFF3B82F6)),
title: const Text('男'),
trailing: const Icon(Icons.chevron_right),
onTap: () => Navigator.pop(context, '男'), // ← 带值返回
),
Divider(height: 1.h, indent: 16, endIndent: 16),
ListTile(
leading: const Icon(Icons.female, color: Color(0xFFF06292)),
title: const Text('女'),
trailing: const Icon(Icons.chevron_right),
onTap: () => Navigator.pop(context, '女'),
),
],
),
);
}
}
```
全程没有 `setState`、没有返回值声明——**StatelessWidget 就够了**,选择器页是最典型的"纯跳转 + 带值返回"场景。
---
## 五、踩坑记录
1. **pop 不带值 = 返回 null**:用系统返回键关页时不会触发任何 `pop(context, value)`,接收侧必须处理 null;
2. **类型要配对**:`push<String>` 对应 `pop(context, '男')`;如果你 push 没写泛型,pop 的值类型就是 dynamic,接收侧要强转;
3. pop 之后本页 context 已失效,别再 await 什么(本页没有异步,天然安全);
4. 更多返回值的真实场景:日期选择、城市选择、筛选条件——结构都和本页一致。
---
## 六、扩展思考
- 接收侧完整代码见 [router_home_page.md](router_home_page.md)(`await push` + `context.mounted` + `?? '未选择'`);
- 参数**传入**的两种通道见 [detail_page.md](detail_page.md)(构造参数 vs 命名路由 arguments);
- 进阶:`Navigator.pop` 可以返回任意类型(对象、Map),比如"选了一个城市"返回整个城市模型,接收侧依然按泛型拿。