# 【Demo】路由首页:三种跳转姿势 > 源文件:`lib/pages/demo/router_home_page.dart` | 分类:路由 > 一句话:push 传参 / await 接返回值 / pushNamed 命名路由 —— 跳转的三个基本姿势。 --- ## 一、这个 Demo 解决什么问题 页面跳转是 App 的基本操作。本页演示三种姿势及其适用场景: 1. **push + 构造函数传参**:参数少、类型安全,最常用; 2. **push 并等待返回结果**:从"选择器页"带值回来(选性别等); 3. **pushNamed 命名路由 + arguments**:按路由名跳转,参数以 Map 传递。 > 核心思想:**页面跳转是"入栈/出栈"**(Navigator 是个栈)。 > push = 压栈,pop = 出栈;pop 时带值 → push 的 await 拿到值。 --- ## 二、怎么运行 / 演示内容 ```dart runApp(const RouterApp()); ``` - 方式 1:跳详情页(张三,18); - 方式 2:跳选择器页,选"男/女" → 返回首页弹 SnackBar 显示选择结果; - 方式 3:跳详情页(李四,25,走命名路由)。 --- ## 三、核心知识点(新手向) ### 1. 方式 1:push + 构造函数传参(类型安全,首选) ```dart Navigator.push( context, MaterialPageRoute( builder: (_) => const DetailPage(name: '张三', age: 18), ), ); ``` - 参数是 Dart 强类型:写错类型编译期就报错; - 页面构造写在 `builder` 里(路由是"惰性构建",进入页面才执行)。 ### 2. 方式 2:await push 接收 pop 返回值 ```dart onPressed: () async { // 注意:push 返回的是 Future,用 await 接收 pop 带回来的值 final result = await Navigator.push( context, MaterialPageRoute(builder: (_) => const PickerPage()), ); if (context.mounted) { // await 之后必须判 mounted! ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('你选择了:${result ?? '未选择'}')), ); } }, ``` - 泛型 `` 声明返回类型; - 用户点系统返回键(没有 pop 带值)→ result 为 null,`?? '未选择'` 兜底; - **await 后 context.mounted 必须判**(页面可能已被销毁)。 ### 3. 方式 3:pushNamed 命名路由 + arguments ```dart Navigator.pushNamed( context, '/detail', // 必须在 MaterialApp.routes 里注册过 arguments: {'name': '李四', 'age': 25}, ); ``` - arguments 是 `dynamic`(任意类型),取值需判空强转(见 [detail_page.md](detail_page.md)); - 适合路由名集中管理的场景,代价是**丢失了类型安全**。 --- ## 四、关键代码剖析 ```dart // 页面底部常驻的知识点提示(学习型 Demo 的惯例) Text( '知识点:页面跳转是【入栈/出栈】。' '返回页 pop 时带值 → 接收页 await push 拿到值。' '命名路由的 arguments 是 dynamic,取值需判空强转。', ) ``` --- ## 五、踩坑记录 1. **`await` 之后用 `context` 必须先判 `context.mounted`**(Flutter 3.7+ 的推荐写法,替代旧式 `if (!mounted) return`); 2. `pushNamed` 没在 routes 注册 → 运行期 `onUnknownRoute` 报错/黑屏; 3. 忘了 `await push` 就收不到 pop 返回值; 4. 返回结果用泛型约束:`Navigator.push`,别让类型随意流转。 --- ## 六、扩展思考 - pop 带值的一方见 [picker_page.md](picker_page.md)(`Navigator.pop(context, '男')`); - 参数接收的两种通道见 [detail_page.md](detail_page.md); - 真实项目推荐 go_router:声明式路由 + 守卫 + 深链,但底层仍是 Navigator 这套入栈/出栈机制。