如何在Go Router中根据栈状态选择性Push或Pop路由?
实现根据回退栈状态自动选择Pop或Push的功能
核心思路是判断当前导航栈中目标页面(Home)是否是当前页面的直接前一个路由,以此决定执行Pop还是Push操作。下面提供两种实用实现方式:
方式一:直接在按钮点击事件中判断(基础版)
假设你使用命名路由管理页面(推荐),给每个页面路由设置唯一名称(比如/home、/profile、/info),代码如下:
ElevatedButton( onPressed: () { final navigator = Navigator.of(context); // 获取当前导航栈的路由名称列表 final routeNames = navigator.routeInformationProvider?.value.routeNames ?? []; // 检查前一个路由是否是Home页面 if (routeNames.length >= 2 && routeNames[routeNames.length - 2] == '/home') { // 前一个页面是Home,执行Pop回到Home navigator.pop(); } else { // 前一个页面不是Home,Push新的Home页面 navigator.pushNamed('/home'); } }, child: const Text('返回首页'), )
方式二:扩展NavigatorState实现自定义方法(优雅版)
如果你希望像context.popOrPush(route)一样调用,可以给NavigatorState写一个扩展类,封装判断逻辑:
// 定义扩展类 extension NavigatorPopOrPushExtension on NavigatorState { void popOrPush(String targetRouteName) { final routeNames = routeInformationProvider?.value.routeNames ?? []; // 判断当前页面的直接前一个路由是否是目标路由 if (routeNames.length >= 2 && routeNames[routeNames.length - 2] == targetRouteName) { pop(); } else { pushNamed(targetRouteName); } } }
使用时只需一行代码:
ElevatedButton( onPressed: () { Navigator.of(context).popOrPush('/home'); }, child: const Text('返回首页'), )
适配非命名路由场景
如果没用命名路由,可以通过路由的settings传递标识,或者直接判断页面类型:
extension NavigatorPopOrPushExtension on NavigatorState { void popOrPushToHome() { Route? previousRoute; var currentRoute = route; // 遍历路由栈,查找前一个页面是否是HomeScreen while (currentRoute != null) { final parentRoute = currentRoute.parent; if (parentRoute != null && parentRoute is MaterialPageRoute) { final pageWidget = parentRoute.builder(context); if (pageWidget.runtimeType == HomeScreen) { previousRoute = parentRoute; break; } } currentRoute = parentRoute; } // 如果前一个页面是Home,执行Pop;否则Push新Home if (previousRoute != null && route.parent == previousRoute) { pop(); } else { push(MaterialPageRoute(builder: (context) => const HomeScreen())); } } }
调用方式:
Navigator.of(context).popOrPushToHome();
内容的提问来源于stack exchange,提问作者commandiron
相关产品推荐
相关产品推荐

