flutter架 构项目基础

This commit is contained in:
崔宝新
2026-09-04 15:22:20 +08:00
parent 70967229d0
commit 0c5aee59c0
265 changed files with 35484 additions and 0 deletions
+107
View File
@@ -0,0 +1,107 @@
# 【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),比如"选了一个城市"返回整个城市模型,接收侧依然按泛型拿。