我目前使用的是Vaadin Flow 版本 14 ( https://github.com/vaadin/platform/releases/tag/14.0.0 )
我运行 Java 版本 1.8.0_231,64 位。
我只是希望能够检测(在 java 中!)每当用户执行以下任一操作时:
- 关闭当前浏览器选项卡(或其浏览器)
- 点击键盘上的 F5,或按浏览器中的刷新按钮
- 点击链接(或其他任何内容),将他们重定向离开我的网站
我尝试了很多不同的方法来检测这一点。到目前为止,我唯一能够检测到的是当前 VaadinSession 何时过期(我可以通过执行 VaadinSession.getCurrent().getSession().setMaxInactiveInterval(15)
来更改)。这使得每个 session 在 15 秒后过期(15 在我的例子中只是一个测试数字)。
借助 Vaadin 8,我相信您可以做到这一点,并且开箱即用:
JavaScript.getCurrent().execute(
"function closeListener() { catchClose(); } " +
"window.addEventListener('beforeunload', closeListener); " +
"window.addEventListener('unload', closeListener);"
);
JavaScript.getCurrent().addFunction("catchClose", arguments ->
{
System.out.println("user has quit :o");
});
我无法使用这个,因为我使用的是Vaadin 14,而不是8。
我尝试将其添加到我的 View 类中:
@Override
protected void onDetach(DetachEvent detachEvent)
{
System.out.println("onDetach " + detachEvent);
}
它仅在 session 过期时打印此消息(在我的例子中为 15 秒)。即使我不关闭页面。
我尝试实现 BeforeLeaveObserver/BeforeLeaveListener 并覆盖它:
@Override
public void beforeLeave(BeforeLeaveEvent beforeLeaveEvent)
{
System.out.println("beforeLeave");
}
这永远不会打印。
我也尝试过所有这些,但它们没有满足我的需要:
VaadinResponse.getCurrent().getService().addUIInitListener(e ->
{
System.out.println("1 addUIInitListener : " + e);
e.getUI().addBeforeLeaveListener(e2 ->
{
System.out.println("1.1 addBeforeLeaveListener : " + e2);
});
e.getUI().addDetachListener(e2 ->
{
System.out.println("1.2 addDetachListener : " + e2);
});
});
VaadinResponse.getCurrent().getService().addServiceDestroyListener(e ->
{
System.out.println("2 addServiceDestroyListener : " + e);
});
VaadinResponse.getCurrent().getService().addSessionDestroyListener(e ->
{
System.out.println("3 addSessionDestroyListener : " + e);
});
1 addUIInitListener
在用户加载页面时打印。
1.1 addBeforeLeaveListener
从不打印。
2 addServiceDestroyListener
永远不会打印。服务与 session 不同。有道理。
1.2
和 3 addSessionDestroyListener
稍后打印 w。不过大约需要 15-30 秒。
有没有办法基本上立即检测到这一点? :/
最佳答案
检测关闭的 JavaScript 方法仍然有效。
语法只是改变了一点
UI.getCurrent().getPage().executeJs("function closeListener() { $0.$server.windowClosed(); } " +
"window.addEventListener('beforeunload', closeListener); " +
"window.addEventListener('unload', closeListener);",getElement());
@ClientCallable
public void windowClosed() {
System.out.println("Window closed");
}
尽管这不是 100% 防弹的方式,因为我认为并非所有浏览器都以相同的方式工作。例如,上面的代码在 Chrome 中触发两次,其中仅监听 beforeunload
就足够了。
这可以简化 JavaScript
UI.getCurrent().getPage().executeJs(
"window.addEventListener('beforeunload', () => $0.$server.windowClosed()); ",getElement());
BeforeLeaveObserver 与导航一起使用。因此,如果您使用 RouterLink 或调用 ui.navigate("route")
,那么 BeforeLeaveEvent 会被调度,但当您调用 page 时则不会.setLocation()
.
浏览器可以因崩溃而关闭,或者因其他原因丢失,那么beforeunload
自然不会发生。最后的手段是基于心跳的检测机制。 IE。心跳丢失 3 次后,Vaadin 服务器将断定浏览器已丢失。这其中自然有延迟,这是无法避免的。
关于java - {Java} Vaadin 14 - 检测用户离开(关闭选项卡、f5 等),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60084612/