解决方法
虽然@CommonSense的答案可行,但我们可以稍微调整一下,避免在GoRouter无法弹出时使用pop。
请记住这一点。最后,这只是一个解决方法,未来特别是在GoRouter升级方面可能会导致意外行为。
void popUntilPath(String routePath) {
final router = GoRouter.of(context);
while (router.location != routePath) {
if (!router.canPop()) {
return;
}
debugPrint('Popping ${router.location}');
router.pop();
}
}
正确的方式?
另一种实现该功能的方式(似乎是正确的实现方式),是使用带有正确路由声明的 .go
,像这样:
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp.router(
title: 'Go Router Demo',
routerConfig: GoRouter(
initialLocation: '/login',
routes: [
GoRoute(
name: '/login',
path: '/login',
builder: (_, __) => const Login(),
routes: [
GoRoute(
name: 'step-1',
path: 'step-1',
builder: (_, __) => const Step1(),
),
GoRoute(
name: 'step-2',
path: 'step-2',
builder: (_, __) => const Step2(),
),
],
),
],
),
);
}
}
class Login extends StatelessWidget {
const Login({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Entry Page')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Login entry page'),
ElevatedButton(
onPressed: () => GoRouter.of(context).pushNamed('step-1'),
child: const Text('Go to step 1'),
),
],
),
),
);
}
}
class Step1 extends StatelessWidget {
const Step1({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Step 1')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Step 1'),
ElevatedButton(
onPressed: () => GoRouter.of(context).pushNamed('step-2'),
child: const Text('Go to step 2'),
),
],
),
),
);
}
}
class Step2 extends StatelessWidget {
const Step2({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Step 2')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Step 2'),
ElevatedButton(
onPressed: () => GoRouter.of(context).goNamed('/login'),
child: const Text('Go to login'),
),
],
),
),
);
}
}
当您调用
goNamed
到
/login
时,它会执行弹出操作直到登录,这正是您想要的。
如果您没有像这样声明路由(也许您正在使用命令式API),GoRouter将会
go
到该路由,但是通过将其添加到堆栈中而不仅仅是删除其他路由。
context.goNamed('/login')
在这种情况下是不起作用的吗?如果有一些路由没有包含在/login
命名路由中,它们将会从栈中移除。 - Peter Koltai