【问题标题】:How to prevent closing browser window?如何防止关闭浏览器窗口?
【发布时间】:2010-09-24 22:08:19
【问题描述】:

我尝试使用以下代码在关闭浏览器窗口时收到警报:

window.onbeforeunload = confirmExit;
function confirmExit() {
  return "You have attempted to leave this page.  If you have made any changes to the fields without clicking the Save button, your changes will be lost.  Are you sure you want to exit this page?";
}

它有效,但如果页面包含一个超链接,单击该超链接会引发相同的警报。我只需要在关闭浏览器窗口而不是单击超链接时显示警报。

【问题讨论】:

  • 投票重新开放。链接的副本不回答问题,但这里的答案可以。
  • FWIW,如果你把这种行为放到我必须使用的任何应用程序中,我会刺伤你的小脚趾。劫持浏览器是解决这个问题的好方法。你不能只使用 AJAX 或其他东西并自动保存它们的状态吗?
  • 我不同意格雷厄姆的观点——有时你只需要一个警告/确认。诚然,这可能(并且经常)被试图阻止您离开的网站滥用,但如果使用得当,它会非常受欢迎,例如,如果您忘记发布某些内容。
  • 如果你想刷新页面还是会遇到问题,即使你禁用了锚事件。

标签: javascript browser window onbeforeunload


【解决方案1】:

我添加了一个额外的代码来处理窗口是否关闭的进一步处理

let disableConfirmation = false;
window.addEventListener('beforeunload', event => {
  const confirmationText = 'Are you sure?';
  if (!disableConfirmation) {
    event.returnValue = confirmationText; // Gecko, Trident, Chrome 34+
    return confirmationText;              // Gecko, WebKit, Chrome <34
  } else {
    // Set flag back to false, just in case
    // user stops loading page after clicking a link.
    disableConfirmation = false;
  }
});

确认后如果你想发送任何ajax请求并且你已经使用了jquery

 $(window).on('unload', function() {
   // async: false will make the AJAX synchronous in case you're using jQuery
   axios
     .get('ajax_url')
     .then(response => {});
 });

如果没有使用 jquery,你可以使用 navigator,它需要 navigator 库

navigator.sendBeacon(url, data);

你可以从这里下载这个库:https://github.com/miguelmota/Navigator.sendBeacon

【讨论】:

    【解决方案2】:

    可以检测超链接点击,但无法判断用户是否:

    • 已尝试刷新页面。
    • 已尝试关闭浏览器选项卡。
    • 试图关闭浏览器窗口。
    • 在 URL 栏中输入了另一个 URL,然后按 Enter。

    所有这些操作都会在window 上生成beforeunload 事件,而没有关于该事件的任何更确切信息。

    为了在执行上述操作时显示确认对话框,而不是在单击超链接时显示,请按照下列步骤操作:

    • beforeunload 事件侦听器分配给window,它将以字符串形式返回确认文本,除非将特定变量(标志)设置为true
    • click 事件分配给document。检查是否已单击 a 元素 (event.target.tagName)。如果是,请将标志设置为true

    您还应该通过将submit 事件侦听器分配给document 来处理表单提交。

    您的代码可能如下所示:

    let disableConfirmation = false;
    window.addEventListener('beforeunload', event => {
      const confirmationText = 'Are you sure?';
      if (!disableConfirmation) {
        event.returnValue = confirmationText; // Gecko, Trident, Chrome 34+
        return confirmationText;              // Gecko, WebKit, Chrome <34
      } else {
        // Set flag back to false, just in case
        // user stops loading page after clicking a link.
        disableConfirmation = false;
      }
    });
    document.addEventListener('click', event => {
      if (event.target.tagName.toLowerCase() === 'a') {
        disableConfirmation = true;
      }
    });
    document.addEventListener('submit', event => {
      disableConfirmation = true;
    });
    <p><a href="https://stacksnippets.net/">google.com</a></p>
    <form action="https://stacksnippets.net/"><button type="submit">Submit</button></form>
    <p>Try clicking the link or the submit button. The confirmation dialog won't be displayed.</p>
    <p>Try reloading the frame (right click -> "Reload frame" in Chrome). You will see a confirmation dialog.</p>

    请注意,在某些浏览器中,您必须在 beforeunload 侦听器中使用 event.returnValue,而在其他浏览器中,您必须使用 return 语句。

    另见beforeunload event docs

    【讨论】:

      【解决方案3】:

      保持您的代码不变并使用 jQuery 处理链接:

      $(function () {
        $("a").click(function {
          window.onbeforeunload = null;
        });
      });
      

      【讨论】:

      • 如果打开的子窗口在另一个域中,这是否有效?
      • 是的,它适用于链接,但请给出一个解决方案,当我们刷新浏览器时 window.onbeforeunload 事件触发我们如何停止在刷新页面或按下返回按钮时触发事件你知道吗关于这个
      • 这个问题没有jQuery标签。
      • @M.UtkuALTINKAYA 你什么意思?这个问题仍然没有jQuery标签。
      • @M.UtkuALTINKAYA 他的意思是这个问题上没有 jQuery 标签,所以你不应该用 jQuery 解决方案来回答。 Vanilla javascript 会是最好的。
      【解决方案4】:

      另一种实现如下,您可以在此网页中找到它: http://ujap.de/index.php/view/JavascriptCloseHook

      <html>
        <head>
          <script type="text/javascript">
            var hook = true;
            window.onbeforeunload = function() {
              if (hook) {
                return "Did you save your stuff?"
              }
            }
            function unhook() {
              hook=false;
            }
          </script>
        </head>
        <body>
          <!-- this will ask for confirmation: -->
          <a href="http://google.com">external link</a>
      
          <!-- this will go without asking: -->
          <a href="anotherPage.html" onClick="unhook()">internal link, un-hooked</a>
        </body>
      </html>
      

      它的作用是将变量用作标志。

      【讨论】:

      • +1 因为它是更通用且更易于访问的解决方案。假设我有一个使页面重定向的脚本部分,所以在应用重定向操作之前,我只需设置hook = false。结帐this DEMO
      • 根据您的解决方案,我建议如果您使用 jQuery,请使用 .noConfirm 之类的类并执行以下操作:$('.noConfirm').click(unhook)
      • @netadictos 我建议您更新答案以使用更现代的.addEventListener() 而不是onclick 属性(或.onbeforeunload = ...)。
      • 我建议您不要使用 addEventListener,因为 onclick 适用于所有浏览器。你仍然可以不显眼地分配 onclick
      • @mplungjan 实际上,addEventListener works 在所有浏览器中。如果你认为 IE attachEvent 方法,功能基本相同。
      猜你喜欢
      • 2010-10-01
      • 2020-06-06
      • 2012-06-23
      • 1970-01-01
      • 2013-01-08
      • 2018-07-30
      • 2018-02-06
      • 1970-01-01
      • 2014-10-14
      相关资源
      最近更新 更多