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

相关推荐
于慨20 小时前
Lambda 表达式、方法引用(Method Reference)语法
java·前端·servlet
石小石Orz20 小时前
油猴脚本实现生产环境加载本地qiankun子应用
前端·架构
从前慢丶20 小时前
前端交互规范(Web 端)
前端
@yanyu66620 小时前
07-引入element布局及spring boot完善后端
javascript·vue.js·spring boot
CHU72903520 小时前
便捷约玩,沉浸推理:线上剧本杀APP功能版块设计详解
前端·小程序
GISer_Jing21 小时前
Page-agent MCP结构
前端·人工智能
王霸天21 小时前
💥别再抄网上的Scale缩放代码了!50行源码教你写一个永不翻车的大屏适配
前端·vue.js·数据可视化
小领航21 小时前
用 Three.js + Vue 3 打造炫酷的 3D 行政地图可视化组件
前端·github
@大迁世界21 小时前
2026年React大洗牌:React Hooks 将迎来重大升级
前端·javascript·react.js·前端框架·ecmascript
PieroPc21 小时前
一个功能强大的 Web 端标签设计和打印工具,支持服务器端直接打印到局域网打印机。Fastapi + html
前端·html·fastapi