简短、错误的答案:
你可以通过以下方式做到这一点处理beforeunload事件并返回一个非空字符串:
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.
});
这种方法的问题在于提交表单也会触发卸载事件。通过添加您正在提交表单的标志可以轻松解决此问题:
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:
<form method="post" onsubmit="setFormSubmitting()">
<input type="submit" />
</form>
但请继续阅读...
长而正确的答案:
您也不想显示此消息当用户没有更改表单上的任何内容时。一种解决方案是使用beforeunload
事件与“脏”标志相结合,只有在确实相关时才会触发提示。
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
方法,有多种方法。
您可以使用jQuery 和表单序列化,但这种方法有一些缺陷。首先,您必须更改代码以适用于任何形式($("form").each()
就可以了),但最大的问题是 jQuery 的serialize()
只适用于命名的、非禁用的元素,因此更改任何禁用的或未命名的元素不会触发脏标志。有解决方法,例如将控件设置为只读而不是启用、序列化然后再次禁用控件。
因此,事件似乎是一条出路。你可以试试监听按键。本次活动有几个问题:
- 不会在复选框、单选按钮或通过鼠标输入更改的其他元素上触发。
- Will trigger for irrelevant keypresses like the Ctrl key.
- 不会触发通过 JavaScript 代码设置的值。
- 通过上下文菜单剪切或粘贴文本时不会触发。
- 不适用于日期选择器或复选框/单选按钮美化器等虚拟输入,它们通过 JavaScript 将其值保存在隐藏输入中。
The change event also 不会触发 JavaScript 代码设置的值,因此也不适用于虚拟输入。
绑定input给所有人的活动inputs (and textareas and selects)在您的页面上不适用于旧版浏览器并且,像上面提到的所有事件处理解决方案一样,不支持撤消。当用户更改文本框然后撤消该操作,或者选中并取消选中复选框时,表单仍然被视为脏表单。
当您想要实现更多行为(例如忽略某些元素)时,您将需要做更多工作。
不要重新发明轮子:
因此,在考虑实施这些解决方案和所有必需的解决方法之前,请意识到您正在重新发明轮子,并且很容易遇到其他人已经为您解决的问题。
如果您的应用程序已经使用 jQuery,您也可以使用经过测试、维护的代码,而不是自己编写代码,并使用第三方库来完成所有这些操作。
jquery.dirty(由 @troseman 在评论中建议)提供了正确检测表单是否已更改的功能,并防止用户在显示提示时离开页面。它还具有其他有用的功能,例如重置表单以及将表单的当前状态设置为“干净”状态。用法示例:
$("#myForm").dirty({preventLeaving: true});
一个较旧的、目前已废弃的项目是jQuery 的你确定吗?插入,效果也很好;看到他们的演示页面。用法示例:
<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 正在推出其中自定义消息也被删除.
本网站其他地方存在一些替代方案,但我认为这样的对话框已经足够清晰了:
您想离开这个网站吗?
您所做的更改可能不会保存。
Leave Stay