在离开未保存更改的网页之前警告用户 [英] Warn user before leaving web page with unsaved changes

查看:26
本文介绍了在离开未保存更改的网页之前警告用户的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序中有一些带有表单的页面.

I have some pages with forms in my application.

我该如何保护表单,以便在有人离开或关闭浏览器选项卡时,系统会提示他们确认他们确实要保留未保存数据的表单?

How can I secure the form in such a way that if someone navigates away or closes the browser tab, they should be prompted to to confirm they really want to leave the form with unsaved data?

推荐答案

简短的错误答案:

您可以通过处理beforeunload 事件并返回一个非空字符串:

Short, wrong answer:

You can do this by handling the beforeunload event and returning a non-null string:

window.addEventListener("beforeunload", function (e) {
    var confirmationMessage = 'It looks like you have been editing something. '
                            + 'If you leave before saving, your changes will be lost.';

    (e || window.event).returnValue = confirmationMessage; //Gecko + IE
    return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc.
});

这种方法的问题在于提交表单也会触发卸载事件.通过添加您正在提交表单的标志可以轻松解决此问题:

The problem with this approach is that submitting a form is also firing the unload event. This is fixed easily by adding the a flag that you're submitting a form:

var formSubmitting = false;
var setFormSubmitting = function() { formSubmitting = true; };

window.onload = function() {
    window.addEventListener("beforeunload", function (e) {
        if (formSubmitting) {
            return undefined;
        }

        var confirmationMessage = 'It looks like you have been editing something. '
                                + 'If you leave before saving, your changes will be lost.';
        
        (e || window.event).returnValue = confirmationMessage; //Gecko + IE
        return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc.
    });
};

然后在提交时调用setter:

Then calling the setter when submitting:

<form method="post" onsubmit="setFormSubmitting()">     
    <input type="submit" />
</form>

但请继续阅读...

您也不希望在用户未对您的表单进行任何更改时显示此消息.一种解决方案是将 beforeunload 事件与dirty"事件结合使用.标志,只有在真正相关时才会触发提示.

You also don't want to show this message when the user hasn't changed anything on your forms. One solution is to use the beforeunload event in combination with a "dirty" flag, which only triggers the prompt if it's really relevant.

var isDirty = function() { return false; }

window.onload = function() {
    window.addEventListener("beforeunload", function (e) {
        if (formSubmitting || !isDirty()) {
            return undefined;
        }
        
        var confirmationMessage = 'It looks like you have been editing something. '
                                + 'If you leave before saving, your changes will be lost.';

        (e || window.event).returnValue = confirmationMessage; //Gecko + IE
        return confirmationMessage; //Gecko + Webkit, Safari, Chrome etc.
    });
};
    

现在要实现 isDirty 方法,有多种方法.

Now to implement the isDirty method, there are various approaches.

您可以使用 jQuery 和表单序列化,但是这种方法有一些缺陷.首先,您必须更改代码以在任何表单上工作($(form").each() 都可以),但最大的问题是 jQuery 的 serialize() 仅适用于已命名的非禁用元素,因此更改任何禁用或未命名的元素都不会触发脏标志.有解决方法,比如将控件设为只读,而不是启用、序列化然后再次禁用控件.

You can use jQuery and form serialization, but this approach has some flaws. First you have to alter the code to work on any form ($("form").each() will do), but the greatest problem is that jQuery's serialize() will only work on named, non-disabled elements, so changing any disabled or unnamed element will not trigger the dirty flag. There are workarounds for that, like making controls readonly instead of enabling, serializing and then disabling the controls again.

所以事件似乎是要走的路.您可以尝试监听按键.这个事件有几个问题:

So events seem the way to go. You can try listening for keypresses. This event has a few issues:

  • 不会在复选框、单选按钮或其他通过鼠标输入更改的元素上触发.
  • 将触发不相关的按键,例如 Ctrl 键.
  • 不会在通过 JavaScript 代码设置的值上触发.
  • 不会在通过上下文菜单剪切或粘贴文本时触发.
  • 不适用于诸如日期选择器或复选框/单选按钮美化器等虚拟输入,它们通过 JavaScript 将其值保存在隐藏输入中.

change 事件不会在从 JavaScript 代码设置的值上触发,因此也不适用于虚拟输入.

The change event also doesn't trigger on values set from JavaScript code, so also won't work for virtual inputs.

input 事件绑定到所有inputs(以及 textareas 和 selects) 在您的页面上不适用于旧浏览器,并且与上面提到的所有事件处理解决方案一样,不支持撤消.当用户更改文本框然后撤消该操作,或选中和取消选中复选框时,该表单仍被认为是脏的.

Binding the input event to all inputs (and textareas and selects) on your page won't work on older browsers and, like all event handling solutions mentioned above, doesn't support undo. When a user changes a textbox and then undoes that, or checks and unchecks a checkbox, the form is still considered dirty.

当您想要实现更多行为(例如忽略某些元素)时,您将有更多工作要做.

And when you want to implement more behavior, like ignoring certain elements, you'll have even more work to do.

因此,在您考虑实施这些解决方案和所有必需的解决方法之前,请意识到您正在重新发明轮子,并且您很容易遇到其他人已经为您解决的问题.

So before you think about implementing those solutions and all required workarounds, realize you're reinventing the wheel and you're prone to running into problems others have already solved for you.

如果您的应用程序已经使用了 jQuery,那么您最好使用经过测试、维护的代码,而不是自己编写代码,并使用第三方库来完成所有这些工作.

If your application already uses jQuery, you may as well use tested, maintained code instead of rolling your own, and use a third-party library for all of this.

jquery.dirty(由@troseman 在评论中建议)为正确检测表单是否已更改,并防止用户在显示提示时离开页面.它还具有其他有用的功能,例如重置表单,以及将表单的当前状态设置为干净"状态.状态.示例用法:

jquery.dirty (suggested by @troseman in the comments) provides functions for properly detecting whether a form has been changed or not, and preventing the user from leaving the page while displaying a prompt. It also has other useful functions like resetting the form, and setting the current state of the form as the "clean" state. Example usage:

$("#myForm").dirty({preventLeaving: true});

一个较旧的、目前已废弃的项目是 jQuery 的你确定吗?插件,也很好用;参见他们的 演示页面.示例用法:

An older, currently abandoned project, is jQuery's Are You Sure? plugin, which also works great; see their demo page. Example usage:

<script src="jquery.are-you-sure.js"></script>

<script>
  $(function() {
    $('#myForm').areYouSure(
      {
        message: 'It looks like you have been editing something. '
               + 'If you leave before saving, your changes will be lost.'
      }
    );
  });
  
</script>

并非所有地方都支持自定义消息

请注意,自 2011 年以来,Firefox 4 不支持自定义消息在这个对话框中.截至 2016 年 4 月,Chrome 51 正在推出 其中的自定义消息也将被删除.

Custom messages not supported everywhere

Do note that since 2011 already, Firefox 4 didn't support custom messages in this dialog. As of april 2016, Chrome 51 is being rolled out in which custom messages are also being removed.

本网站的其他地方存在一些替代方案,但我认为这样的对话已经足够清楚:

Some alternatives exist elsewhere on this site, but I think a dialog like this is clear enough:

你想离开这个网站吗?

您所做的更改可能无法保存.

Changes you made may not be saved.

离开 留下

这篇关于在离开未保存更改的网页之前警告用户的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆