使用jQuery / JavaScript阻止任何形式的页面刷新


92

用户进入我的页面后,我不希望他刷新页面。

  1. 用户可以随时点击F5顶部的“刷新”按钮。他应该警惕地说

    您无法刷新页面。

  2. 另外,如果用户打开一个新选项卡并尝试访问上一个选项卡中的相同URL,他也将收到警报

    您无法在2个标签中打开同一页面

无论如何,我可以使用JavaScript或jQuery来做到这一点?第一点非常重要。


您可以使用广播频道API(developer.mozilla.org/en-US/docs/Web/API/Broadcast_Channel_API)进行检测,并发送味精以在选项卡之间进行通信。这样,您可以使用相同的网址检测多个标签,并阻止其他标签。
aXuser264

Answers:


191

#1可以通过实现window.onbeforeunload

例如:

<script type="text/javascript">
    window.onbeforeunload = function() {
        return "Dude, are you sure you want to leave? Think of the kittens!";
    }
</script>

系统将提示用户该消息,并为用户提供停留在页面上或继续前进的选项。这变得越来越普遍。如果您在键入帖子时尝试离开页面,则Stack Overflow会执行此操作。您不能完全阻止用户进行重新加载,但是如果用户这样做,则听起来确实很吓人。

#2或多或少是不可能的。即使您跟踪会话和用户登录,您仍然不能保证您正确检测到第二个选项卡。例如,也许我打开了一个窗口,然后将其关闭。现在我打开一个新窗口。即使我已经关闭了第一个选项卡,您也可能会将其检测为第二个选项卡。现在,您的用户因为已关闭而无法访问第一个窗口,并且由于您拒绝而无法访问第二个窗口。

实际上,我的银行的在线系统确实在努力做到第二点,并且上述情况一直在发生。通常,我必须等到服务器端会话到期后才能再次使用银行系统。


1
请注意,onbeforeunload事件在Opera浏览器的版本中不可用。
WillyCornbread

1
如果用户选择停留在页面上,有没有办法做某事。
riship89年

5
尽管为跨浏览器兼容性并防止了库问题,尽管应该使用window.addEventListener(请参阅developer.mozilla.org/en-US/docs/Web/Events/beforeunload)代替,但对我来说却有用。
JulienBérubé2014年

我知道这个问题很老,但是,如果他们真的想阻止多个会话,他们可以使用WebSockets吗?
梅根(Meghan)2015年

1
@Sean-是的...如果您真的想阻止多个会话。WebSocket可以进行有状态的双向通信。WebSocket连接时,客户端(可能)不会突然变成其他人,因此您应该能够为该用户分配令牌,并在套接字关闭后将其清除。但是,它是围绕用户代理的预期行为而行,因此可能是不良的UX。我能想到的情况很少,像这样的事情比较合适(也许是在线游戏-防止某人以两条 37级死亡之爪的身份登录...)。
塞斯

35

您不能阻止用户刷新,也不能真正尝试。您应该回到为什么需要此解决方案的地方,这里的根本问题是什么?从那里开始,找到解决问题的另一种方法。也许您已详细说明了为什么您认为需要这样做,这将有助于找到这样的解决方案。

打破基本的浏览器功能绝不是一个好主意,超过99.999999999%的Internet可以使用F5进行工作并刷新,这是用户的期望,您不应该破坏它。


问题是该页面是siebel应用程序。当用户处于会话中并单击刷新时,会创建一个新会话,并且应用程序崩溃。因此我需要用户无法刷新。
pankaj 2010年

20
@pankaj-应该在应用程序站点上固定,例如在cookie上,以便用户跨选项卡共享会话。
尼克·克拉弗

9
我不确定你从哪里来。如果您的表单脏了,互联网上无数的站点会阻止浏览器刷新,从而提醒您可能丢失更改。不确定为什么这会“破坏浏览器的基本功能”。
Siraris '18

1
@Siraris:是的。另外,我正在制作一个私有应用程序,即使用户不在私有网络中,该应用程序也应该能够使用。因此,我将所有内容存储在浏览器存储中以供脱机使用,但是如果他重新加载页面,则整个应用程序都将消失。它可能不是很“正常”,但是在这个现代的IT世界中,它将越来越多。
cslotty

15

虽然禁用F5键不是一个好主意,但是您可以在JQuery中执行以下操作。

<script type="text/javascript">
function disableF5(e) { if ((e.which || e.keyCode) == 116 || (e.which || e.keyCode) == 82) e.preventDefault(); };

$(document).ready(function(){
     $(document).on("keydown", disableF5);
});
</script>

希望这会有所帮助!


27
OSX是什么呢,它是CMD + R?或手机上有需要按下的按钮?我不认为这是解决方案
ItalyPaleAle 2015年

14

早在CGI的早期,我们就有许多形式可以触发各种后端操作。例如向群组发送文本通知,打印作业,数据收集等。

如果用户在页面上说“请稍候...执行一些可能需要一些时间的巨大工作”。他们更有可能击中REFRESH,这很糟糕!

为什么?因为这将触发更多缓慢的工作,并最终使整个工作陷入困境。

解决方案?让他们做他们的形式。当他们提交表单时...开始工作,然后将他们定向到另一个页面,告诉他们等待。

中间页面实际保存开始作业所需的表单数据的位置。但是,“等待”页面包含一个JavaScript历史记录销毁。因此,他们可以重新加载等待的页面,并且永远不会触发原始作业在后台启动,因为WAIT页面仅包含WAIT本身所需的表单数据。

希望有道理。

历史记录销毁功能还阻止他们单击“上一步”,然后刷新。

这是非常无缝的,并且在很多年以前都非常有效,直到非营利组织破产。

示例:FORM ENTRY-收集他们的所有信息,并在提交后触发您的后端工作。

来自表单项的响应-返回HTML,该HTML执行重定向到您的静态等待页面和/或POST / GET到另一个表单(WAIT页面)。

等待页面-仅包含与等待页面相关的FORM数据以及用于破坏最新历史记录的JavaScript。像(-1 OR -2)仅破坏最新页面,但仍允许它们返回其原始FORM输入页面。

一旦进入您的WAIT页面,他们就可以根据需要单击REFRESH,并且它永远不会在后端产生原始的FORM作业。相反,您的WAIT页面应该包含一个META定时刷新本身,以便它可以始终检查其工作状态。他们的工作完成后,他们将从等待页面重定向到您想要的任何地方。

如果他们手动刷新,则只需在其中再添加一份工作状态检查。

希望能有所帮助。祝好运。


2
您没有获得足够的信誉,无法获得这个令人惊讶且内容丰富的答案。谢谢!!
ShiningLight '16


2

通过将套接字实现(例如websocket,socket.io等)与用户参与的每个会话一起使用自定义心跳,可以实现数字(2)。如果用户尝试打开另一个窗口,则需要进行javascript处理程序检查如果可以,请与服务器联系,然后返回错误消息。

但是,一个更好的解决方案是尽可能同步两个会话,例如google docs。


2

现在可以使用BroadcastAPI解决问题2 。

目前,仅在Chrome,Firefox和Opera中可用。

var bc = new BroadcastChannel('test_channel');

bc.onmessage = function (ev) { 
    if(ev.data && ev.data.url===window.location.href){
       alert('You cannot open the same page in 2 tabs');
    }
}

bc.postMessage(window.location.href);
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.