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 选择,而是架构选择。

相关推荐
冻感糕人~5 分钟前
【珍藏必备】ReAct框架实战指南:从零开始构建AI智能体,让大模型学会思考与行动
java·前端·人工智能·react.js·大模型·就业·大模型学习
程序员agions9 分钟前
2026年,“配置工程师“终于死绝了
前端·程序人生
alice--小文子15 分钟前
cursor-mcp工具使用
java·服务器·前端
晚霞的不甘24 分钟前
揭秘 CANN 内存管理:如何让大模型在小设备上“轻装上阵”?
前端·数据库·经验分享·flutter·3d
小迷糊的学习记录33 分钟前
0.1 + 0.2 不等于 0.3
前端·javascript·面试
空&白1 小时前
vue暗黑模式
javascript·vue.js
梦帮科技1 小时前
Node.js配置生成器CLI工具开发实战
前端·人工智能·windows·前端框架·node.js·json
飞凌嵌入式1 小时前
用「EN 18031认证」通关欧盟,这张 “网络安全护照” 已就位
网络·安全·能源
Trouvaille ~1 小时前
TCP Socket编程实战(三):线程池优化与TCP编程最佳实践
linux·运维·服务器·网络·c++·网络协议·tcp/ip
VT.馒头2 小时前
【力扣】2695. 包装数组
前端·javascript·算法·leetcode·职场和发展·typescript