Chuyển đến nội dung chính

第 5 課:導航與路線選擇

導航器2.0,GoRouter。命名路由、路徑參數、查詢參數。嵌套導航、選項卡導航、抽屜式導航。深層鏈接,路線守衛。

💻 程式設計 — 第 5 課 第 5 課:導航與路線選擇

Flutter 和 Dart:從基礎到高級

第 2 部分:導航和狀態管理

亞洲開發網

1.GoRouter設定

# pubspec.yaml
dependencies:
  go_router: ^14.0.0
final router = GoRouter(
  initialLocation: '/',
  routes: [
    GoRoute(
      path: '/',
      builder: (context, state) => const HomePage(),
    ),
    GoRoute(
      path: '/products',
      builder: (context, state) => const ProductListPage(),
      routes: [
        GoRoute(
          path: ':id',
          builder: (context, state) {
            final id = state.pathParameters['id']!;
            return ProductDetailPage(id: id);
          },
        ),
      ],
    ),
    GoRoute(
      path: '/search',
      builder: (context, state) {
        final query = state.uri.queryParameters['q'] ?? '';
        return SearchPage(query: query);
      },
    ),
  ],
  redirect: (context, state) {
    final isLoggedIn = authNotifier.isLoggedIn;
    if (!isLoggedIn && state.matchedLocation.startsWith('/dashboard')) {
      return '/login';
    }
    return null;
  },
);

2. 導航

// Programmatic navigation
context.go('/products');
context.push('/products/123');
context.pop();

// Named routes
context.goNamed('productDetail', pathParameters: {'id': '123'});

3. Shell 路由(選項卡導航)

ShellRoute(
  builder: (context, state, child) {
    return MainShell(child: child);
  },
  routes: [
    GoRoute(path: '/home', builder: (_, __) => const HomePage()),
    GoRoute(path: '/explore', builder: (_, __) => const ExplorePage()),
    GoRoute(path: '/profile', builder: (_, __) => const ProfilePage()),
  ],
);

class MainShell extends StatelessWidget {
  final Widget child;
  const MainShell({super.key, required this.child});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: child,
      bottomNavigationBar: NavigationBar(
        selectedIndex: _calculateIndex(GoRouterState.of(context).matchedLocation),
        destinations: const [
          NavigationDestination(icon: Icon(Icons.home), label: 'Home'),
          NavigationDestination(icon: Icon(Icons.explore), label: 'Explore'),
          NavigationDestination(icon: Icon(Icons.person), label: 'Profile'),
        ],
        onDestinationSelected: (index) {
          switch (index) {
            case 0: context.go('/home');
            case 1: context.go('/explore');
            case 2: context.go('/profile');
          }
        },
      ),
    );
  }
}

下一篇: 使用 Riverpod 進行狀態管理。