Flutter:如何结合go_router实现多页面共用Scaffold?
一、基于go_router实现多页面共用Scaffold的方案
核心思路是利用go_router的嵌套路由机制,将共用的Scaffold作为父路由的页面载体,子路由的内容通过RouterOutlet渲染在Scaffold的body区域。这样导航时,Scaffold会始终保留,仅更新body内的子页面,同时完全支持push/pop/go等标准导航方法。
1. 实现步骤
(1)定义共用Scaffold组件
这个组件作为父路由的页面,包含所有需要共用的元素(如AppBar、抽屉、浮动按钮等),并通过RouterOutlet预留子页面的渲染位置:
import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; class SharedScaffold extends StatelessWidget { const SharedScaffold({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('全局共用Scaffold'), backgroundColor: Colors.blue, ), // 子路由页面会渲染在这里 body: const RouterOutlet(), // 示例:共用的浮动按钮,点击跳转到详情页 floatingActionButton: FloatingActionButton( onPressed: () => context.push('/detail'), child: const Icon(Icons.arrow_forward), ), // 示例:共用的侧边抽屉 drawer: Drawer( child: ListView( padding: EdgeInsets.zero, children: [ const DrawerHeader( decoration: BoxDecoration(color: Colors.blue), child: Text('菜单'), ), ListTile( title: const Text('首页'), onTap: () => context.go('/home'), ), ListTile( title: const Text('设置'), onTap: () => context.push('/settings'), ), ], ), ), ); } }
(2)配置go_router嵌套路由
将共用Scaffold作为父路由,所有业务页面作为子路由挂载到父路由下:
final router = GoRouter( // 初始路由直接跳转到首页子路由 initialLocation: '/home', routes: [ // 父路由:承载共用Scaffold GoRoute( path: '/', builder: (context, state) => const SharedScaffold(), // 子路由:所有需要共用Scaffold的页面 routes: [ GoRoute( path: 'home', builder: (context, state) => const HomePage(), ), GoRoute( path: 'detail', builder: (context, state) => const DetailPage(), ), GoRoute( path: 'settings', builder: (context, state) => const SettingsPage(), ), // 支持带参数的子路由 GoRoute( path: 'detail/:id', builder: (context, state) => DetailPageWithId(id: state.pathParameters['id']!), ), ], ), ], );
(3)业务页面示例
业务页面只需专注自身内容,无需再包裹Scaffold:
class HomePage extends StatelessWidget { const HomePage({super.key}); @override Widget build(BuildContext context) { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Text('首页内容'), ElevatedButton( onPressed: () => context.push('/detail/123'), child: const Text('跳转到带参数的详情页'), ), ], ), ); } }
2. 方案优势
- 完全使用go_router标准导航方法(
push/pop/go),无需手动管理索引或页面切换逻辑 - Scaffold仅初始化一次,避免重复创建共用组件,性能更优
- 支持所有go_router的高级特性(路由守卫、深度链接、参数传递等)
二、go_router vs GetX 导航库对比
1. 标准性
- go_router是Flutter官方推荐的路由库,由Flutter团队维护,完全遵循Flutter原生路由规范,与Flutter生命周期、状态管理等特性深度兼容,是当前路由方案的行业标准。
- GetX是第三方全栈库,导航只是其众多功能之一,虽然社区流行,但不属于官方生态,规范上与Flutter原生贴合度不如go_router。
2. 功能强大性
go_router
- 专注于路由领域,功能专业且全面:支持嵌套路由、状态保留路由(
StatefulShellRoute)、类型安全参数、路由守卫、深度链接、多模块路由拆分等。 - 适合复杂路由场景(如大型项目、需要深度链接、多页面嵌套的应用)。
GetX
- 导航功能相对轻量化,支持基础的页面跳转、参数传递,但在复杂嵌套路由、深度链接、路由状态保留等场景下的处理能力不如go_router。
- 优势在于集成了状态管理、依赖注入等功能,适合小型项目或希望用单一库搞定多需求的场景。
3. 选型建议
- 若项目对路由功能要求较高(如复杂嵌套、深度链接、路由权限控制),优先选择go_router。
- 若项目规模较小,需要同时实现状态管理+导航,且路由场景简单,可以考虑GetX。
内容的提问来源于stack exchange,提问作者dev.vinod
相关产品推荐
相关产品推荐

