flutter_modular 5.0.3导航异常:路由未找到与守卫异常排查
问题解决:flutter_modular子路由导航及守卫异常处理
核心问题拆解
- 导航路径错误:直接调用
/tasks是根路径下的路由,而你的/tasks是RecruiterModule下的子路由,根路径不存在该路由;调用/recruiter/tasks触发守卫异常,因为模块级守卫会校验所有子路由,而你的守卫逻辑存在异步处理不及时、角色判断时机错误的问题。 - 守卫逻辑缺陷:
AuthGuard中触发bloc事件后直接返回当前状态,未等待异步状态更新完成RoleGuardVerify在模块初始化时就判断用户状态,此时bloc可能还未完成初始化,导致守卫逻辑错误
解决方案
1. 正确的子路由导航方式
在RecruiterLandingPage中,使用相对路径导航到子路由,无需带上模块前缀:
// 正确写法:相对路径导航到当前模块的子路由 Modular.to.navigate('tasks'); // 或者显式相对路径 Modular.to.navigate('./tasks');
如果一定要用绝对路径,需要确保完整路径匹配模块路由+子路由,但相对路径更灵活,适配模块挂载路径变化。
2. 修复AuthGuard异步逻辑
修改AuthGuard,等待bloc状态加载完成后再判断登录状态:
import 'package:/authentication/ui/bloc/user_status/user_status_bloc.dart'; import 'package:flutter_modular/flutter_modular.dart'; import 'package:bloc/bloc.dart'; class AuthGuard extends RouteGuard { AuthGuard() : super(); @override Future<bool> canActivate(String path, ModularRoute router) async { final bloc = Modular.get<UserStatusBloc>(); // 只在未加载状态时触发加载 if (bloc.state is! UserStatusLogin && bloc.state is! UserStatusLogout) { bloc.add(UserStatusLoadStarted()); } // 等待状态变为登录或登出 final state = await bloc.stream.firstWhere( (state) => state is UserStatusLogin || state is UserStatusLogout, ); return state is UserStatusLogin; } }
3. 重构RoleGuard逻辑
将角色判断逻辑移到RoleGuard的canActivate方法中,避免在模块初始化时提前判断状态:
修改RoleGuardVerify,返回带角色类型的RoleGuard即可:
import 'package:---/app/role_guard.dart'; import 'package:flutter_modular/flutter_modular.dart'; class RoleGuardVerify { static final int RECRUITER = 1; static final int CONSULTANT = 2; static final int MANAGER = 3; Map<int, String> redirectByRole = { RECRUITER: "/recruiter", CONSULTANT: "/consultant", MANAGER: "/manager" }; RouteGuard getGuard(int guardRoleType) { // 直接返回RoleGuard,把判断逻辑放到RoleGuard内部 return RoleGuard(guardRoleType); } }
实现正确的RoleGuard:
import 'package:----/authentication/ui/bloc/user_status/user_status_bloc.dart'; import 'package:flutter_modular/flutter_modular.dart'; class RoleGuard extends RouteGuard { final int requiredRole; RoleGuard(this.requiredRole) : super(); @override Future<bool> canActivate(String path, ModularRoute router) async { final bloc = Modular.get<UserStatusBloc>(); // 确保状态已加载 final state = await bloc.stream.firstWhere( (state) => state is UserStatusLogin || state is UserStatusLogout, ); if (state is! UserStatusLogin) { Modular.to.navigate('/login'); return false; } final user = (state as UserStatusLogin).user; // 判断用户角色是否匹配要求 if (user.role == requiredRole) { return true; } else { // 根据角色重定向到对应模块 final redirectPath = RoleGuardVerify().redirectByRole[user.role] ?? '/recruiter'; Modular.to.navigate(redirectPath); return false; } } }
4. 确保路由配置正确
确认RecruiterModule的路由结构无误:
// RecruiterModule的路由 @override List<ModularRoute> get routes => [ ChildRoute('/', child: (context, args) => RecruiterLandingPage(), children: [ ChildRoute('/tasks', child: (context, args) => TasksPage(), transition: TransitionType.noTransition, ), ], ), ];
验证要点
- 导航时使用相对路径
tasks,确保子路由在RouterOutlet中正确渲染 - 测试未登录状态下的重定向是否正常
- 测试不同角色用户访问时的重定向逻辑是否正确
内容的提问来源于stack exchange,提问作者Sahil Kumar
相关产品推荐
相关产品推荐

