Flutter 路由从 Navigator 到 go_router:嵌套路由 / 登录守卫 / 深链一次讲透

这篇文章解决的核心问题(开宗明义)

Flutter 路由并不难,难的是:

  • 页面多了以后,怎么"管栈"

  • 登录态变化,怎么"统一跳转"

  • 深链 / 外部唤起,怎么"不写一堆 if else"

Dart 复制代码
Navigator.push(
  context,
  MaterialPageRoute(builder: (_) => DetailPage(id: 1)),
);

优点

  • 简单、直观

  • Demo / 小工具非常合适

问题(真实项目一定会遇到)

  • 页面跳转分散在各处

  • 登录判断写在 UI 里

  • 页面栈不可控(返回顺序混乱)

  • 深链几乎没法优雅接入

👉 本质问题:

Navigator 1.0 是"命令式跳转",不是"路由系统"。

  • RouterDelegate

  • RouteInformationParser

  • 声明式页面栈

👉 方向是对的,但:

  • API 复杂

  • 维护成本高

  • 中小团队几乎不会手写

3️⃣ go_router:官方认可的"工程解法"

go_router 的定位一句话:

用"声明式路由 + 状态驱动跳转",解决真实 App 的路由问题

二、go_router 的核心设计思想(这段是你文章的"含金量")

1️⃣ 路由 = 状态映射,而不是 push 行为

Dart 复制代码
GoRoute(
  path: '/detail/:id',
  builder: (context, state) {
    final id = state.pathParameters['id'];
    return DetailPage(id: id);
  },
);

一句关键话:

UI 跳转不是"我要去哪",而是"当前状态对应哪个页面"。

2️⃣ 路由树 ≠ 页面树(这是很多人不懂的点)

Dart 复制代码
GoRoute(
  path: '/',
  builder: (_, __) => HomePage(),
  routes: [
    GoRoute(
      path: 'profile',
      builder: (_, __) => ProfilePage(),
    ),
  ],
);
  • /
  • /profile

👉 这是"嵌套路由",不是嵌套 Widget

三、嵌套路由:Tab / 子页面 / 页面栈治理

典型场景

  • BottomNavigation

  • 主页面 + 子功能页

  • 多模块 App

ShellRoute(一定要写)

Dart 复制代码
ShellRoute(
  builder: (context, state, child) {
    return Scaffold(
      body: child,
      bottomNavigationBar: BottomNav(),
    );
  },
  routes: [
    GoRoute(path: '/home', builder: ...),
    GoRoute(path: '/profile', builder: ...),
  ],
);

一个常见坑

❌ 不要用多个 Navigator 去硬拼

✅ 用 ShellRoute 统一管理"壳结构"

四、登录守卫(这部分你可以写得非常强)

1️⃣ 传统写法的问题

Dart 复制代码
onPressed: () {
  if (!loggedIn) {
    Navigator.push(LoginPage());
  }
}

❌ 登录逻辑散落

❌ 无法统一控制

❌ 深链直接绕过

2️⃣ go_router 的 redirect:登录态统一入口

Dart 复制代码
final router = GoRouter(
  redirect: (context, state) {
    final loggedIn = authRepo.isLogin;
    final loggingIn = state.location == '/login';

    if (!loggedIn && !loggingIn) return '/login';
    if (loggedIn && loggingIn) return '/';

    return null;
  },
);

💡 总结 (非常重要):

登录不是 UI 行为,而是"全局路由约束"。

五、深链(Deep Link):App 真正"像一个系统"的标志

1️⃣ 什么是深链

  • 外部 URL 直接打开某页面

  • 推送 / H5 / 浏览器唤起 App

2️⃣ go_router 天然支持

Dart 复制代码
GoRoute(
  path: '/product/:id',
  builder: (_, state) {
    final id = state.pathParameters['id']!;
    return ProductPage(id: id);
  },
);

系统唤起:

myapp://product/123

👉 不用手动解析,不用 if else

六、页面返回 & 参数回传

复制代码
final result = await context.push('/select');

context.pop(selectedValue);

📌 强调一句:

go_router 并没有"剥夺 Navigator 能力",只是统一了入口。

七、真实项目推荐路由结构(直接给模板)

Dart 复制代码
lib/
 ├─ router/
 │   ├─ app_router.dart
 │   ├─ auth_guard.dart
 │   └─ routes.dart
 ├─ pages/
 ├─ features/
Dart 复制代码
final router = GoRouter(
  routes: appRoutes,
  redirect: authRedirect,
);

👉 这是"团队可复制"的结构

八、Navigator vs go_router 对照总结

维度 Navigator go_router
跳转方式 命令式 声明式
登录控制 分散 集中
深链 困难 原生支持
页面栈 难管理 可预测
项目规模 小 中大型

一句收尾金句:

Flutter 项目一旦进入"多模块 + 登录态 + 深链"阶段,

路由不再是 API 选择,而是架构选择。

相关推荐
像我这样帅的人丶你还9 分钟前
我html生成的doc文档为何在手机文档显示不了图片?
前端·javascript
前端双越老师2 小时前
程序员 1v1 访谈系列第十期:纯前端坚持不了多久了
前端·ai编程·全栈
聪明蛋子哟2 小时前
大模型应用“最后一公里”:从Prompt工程到MCP协议,如何实现跨系统的高可用集成?
网络·prompt
科创致远3 小时前
ESOP 电子作业指导书 WiFi 网络应用实测报告
运维·服务器·网络
承渊政道3 小时前
Linux网络学习【从NAT与代理服务理解网络转发、探索内网穿透原理、再到认识DNS与ICMP、最后动手部署并测试内网穿透】
linux·网络·学习·内网穿透·dns·nat
最强小杰3 小时前
minimax-m3 突然报 HTTP 529 怎么办?连续重试为何更难恢复,退避时间该怎么算?
网络·网络协议·http·ai
门思科技3 小时前
LoRaWAN 网络排障的五层漏斗:从"上不到云"到"数值不对",每一层该用什么工具证明
前端
计算机魔术师3 小时前
Cursor 官方插件商城现恶意 Claude Code 扩展,约 11 小时影响最多 5000 名开发者
前端
程序员清风3 小时前
AI 编程助手的权限边界:文件、命令、密钥与人工确认
运维·服务器·网络
掘金者阿豪3 小时前
MongoDB迁移到金仓数据库:商品属性继续灵活存,订单报表交给 SQL
前端·后端