六、路由与导航

目录

  • 1. 如何实现页面跳转?
  • 2. 命名路由(Named Route)是什么?如何定义?
  • 3. 如何传递参数给路由?
  • 4. 如何返回结果给上一个页面?
  • 5. 什么是路由守卫?如何实现?

1. 如何实现页面跳转?

在 Flutter中,页面跳转通过 Navigator 管理路由栈实现:

// 1. 基本跳转
Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => SecondPage()),
);

// 2. 带返回结果的跳转
final result = await Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => SelectionPage()),
);

// 3. 返回上一页
Navigator.pop(context); 
// 或带返回值返回
Navigator.pop(context, '返回的数据');

2. 命名路由(Named Route)是什么?如何定义?

命名路由:通过字符串标识符管理路由,提高可维护性。

定义步骤:

  1. 声明路由表
MaterialApp(
  initialRoute: '/',
  routes: {
    '/': (context) => HomePage(),
    '/details': (context) => DetailPage(),
    '/settings': (context) => SettingsPage(),
  },
);
  1. 跳转到命名路由
Navigator.pushNamed(context, '/details');
  1. 带参数跳转
Navigator.pushNamed(
  context,
  '/details',
  arguments: {'id': 100, 'name': 'Flutter'}, // 参数传递
);

3. 如何传递参数给路由?

  1. 通过构造函数(推荐)
// 目标页面
class DetailPage extends StatelessWidget {
  final int id;
  final String name;

  DetailPage({required this.id, required this.name});

  // ...
}

// 跳转时传递
Navigator.push(
  context,
  MaterialPageRoute(
    builder: (context) => DetailPage(id: 100, name: 'Flutter'),
  ),
);
  1. 通过路由参数(命名路由)
// 目标页面获取参数
class DetailPage extends StatelessWidget {
  
  Widget build(BuildContext context) {
    final args = ModalRoute.of(context)!.settings.arguments as Map;
    final id = args['id'];
    final name = args['name'];
    // ...
  }
}

// 跳转时传递参数
Navigator.pushNamed(
  context,
  '/details',
  arguments: {'id': 100, 'name': 'Flutter'},
);

4. 如何返回结果给上一个页面?

步骤:

  1. 跳转时等待结果
final result = await Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => SelectionPage()),
);

print('收到结果: $result'); // 处理返回结果
  1. 返回页面时发送结果
// 在 SelectionPage 中
ElevatedButton(
  onPressed: () {
    Navigator.pop(context, '用户选择了A'); // 返回结果
  },
  child: Text('选项A'),
)

5. 什么是路由守卫?如何实现?

路由守卫:在路由跳转前后执行拦截逻辑(如权限验证、日志记录)。

实现方式:

使用 MaterialApponGenerateRouteonGenerateInitialRoutes

MaterialApp(
  onGenerateRoute: (settings) {
    // 路由守卫逻辑
    if (_needLogin(settings.name) && !isLoggedIn) {
      return MaterialPageRoute(  // 拦截并重定向
        builder: (context) => LoginPage(),
      );
    }

    // 正常路由处理
    switch (settings.name) {
      case '/details':
        return MaterialPageRoute(
          builder: (context) => DetailPage(),
          settings: settings,  // 传递原始参数
        );
        // ...其他路由
    }
  },
);

常见守卫场景:

onGenerateRoute: (settings) {
  // 1. 权限验证
  if (settings.name == '/admin' && !isAdmin) {
    return MaterialPageRoute(builder: (_) => AccessDeniedPage());
  }

  // 2. 数据预加载
  if (settings.name == '/profile') {
    final userId = settings.arguments as String;
    precacheUserData(userId); // 预加载数据
  }

  // 3. 路由日志
  logRouteChange(settings.name);

  // ...正常路由处理
}

完整示例:

MaterialApp(
  onGenerateRoute: (settings) {
    // 身份验证守卫
    final requireAuth = ['/profile', '/settings'].contains(settings.name);
    if (requireAuth && !isAuthenticated) {
      return MaterialPageRoute(
        builder: (_) => LoginPage(),
        settings: RouteSettings(name: '/login'), // 重设路由名
      );
    }

    // 参数验证守卫
    if (settings.name == '/product' && settings.arguments == null) {
      return MaterialPageRoute(builder: (_) => NotFoundPage());
    }

    // 路由匹配
    switch (settings.name) {
      case '/product':
        final productId = settings.arguments as String;
        return MaterialPageRoute(
          builder: (_) => ProductPage(id: productId),
        );
      default:
        return MaterialPageRoute(builder: (_) => HomePage());
    }
  },
);

你可能感兴趣的:(Flutter,flutter,navigator)