如何在 flutter web 中使用 Go Router 在浏览器后退按钮或 onReload 页面上显示警报对话框?

Hap*_*iya 8 flutter gorouter flutter-navigation flutter-web flutter-go-router

我正在开发 Flutter Web并使用go_router进行导航。

期望: 从初始路线开始,当用户尝试使用浏览器后退按钮导航回来或重新加载页面时,应显示一个警告框并询问“您确定要退出吗?” 用户交互页面上的消息类型允许退出或停留在同一页面上。

尝试过的方法:

1.WillPopScope:

我在 HomeRoute Widget 上添加了 WillPopScope 小部件来检测 popCallBack。但不知何故,按下后退按钮时不会触发它,因为我可能使用了 go_router 进行导航。

通过执行下面的语句,我无法在控制台 onBack 事件上打印日志。

return WillPopScope(
      onWillPop: () async {
        print("on Will Pop is Called");
        return false;
      },
      child: PaintScaffold(...)
);
Run Code Online (Sandbox Code Playgroud)

MaterialApp.router 的 BackButtonDispatcher 仅适用于 android,不适用于 web。所以这是行不通的。参考之。

2. onBeforeUnload 监听器

我尝试在index.html 文件中添加脚本来检测onBeforeUnload 事件。但它的行为却出人意料。它在 chrome 浏览器中工作正常,但在 safari 中,按下后退按钮时不会显示警报框。但要努力重新加载页面。

在 iOS safari 浏览器上,当页面卸载时,在任何情况下都不会触发 onBeforeUnload。

  <script>
    window.addEventListener('load', function(ev) {
      // Download main.dart.js
      _flutter.loader.loadEntrypoint({
        serviceWorker: {
          serviceWorkerVersion: serviceWorkerVersion,
        }
      }).then(function(engineInitializer) {
        return engineInitializer.initializeEngine();
      }).then(function(appRunner) {
        return appRunner.runApp();
      });
    });

     window.onunload = window.onbeforeunload = function(){
       return 'Are you sure you want to leave?';
     };
  </script>
Run Code Online (Sandbox Code Playgroud)

那么,当用户尝试退出页面时,是否有其他方法可以解决此问题,然后会显示一个警告框以要求确认?

谢谢。

kri*_*yaa 0

延伸ObserverNavigatorObserver


代码

 GoRouter(
  initialLocation: '/',
  navigatorKey: _rootNavigatorKey,
  observers: [
    GoRouterObserver(),  Specify your observer here
  ],
  routes: [
    GoRoute(
      ...
    )
    GoRoute(
      ...
    ),
  ],
);

class GoRouterObserver extends NavigatorObserver {
  @override
  void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
    showDialog()  Here show your dialog box
  }

  @override
  void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
   showDialog()  Here show your dialog box
  }

  @override
  void didRemove(Route<dynamic> route, Route<dynamic>? previousRoute) {
   showDialog()  Here show your dialog box
  }

  @override
  void didReplace({Route<dynamic>? newRoute, Route<dynamic>? oldRoute}) {
    showDialog()  Here show your dialog box
  }
}
Run Code Online (Sandbox Code Playgroud)