You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 19:22:46