Window: beforeunload 事件

beforeunload 事件在当前窗口、包含的文档以及关联资源即将卸载时触发。此时文档仍然可见,并且事件仍然可以取消。

此事件的主要用例是触发浏览器生成的确认对话框,该对话框询问用户是否真的要离开页面,当他们尝试关闭或重新加载页面,或导航到其他地方时。这旨在帮助防止未保存数据的丢失。

可以通过以下方式触发对话框

  • 调用事件对象的 preventDefault() 方法。
  • 将事件对象的 returnValue 属性设置为非空字符串值或任何其他 truthy 值。
  • 从事件处理程序函数返回任何 truthy 值,例如 return "string"。请注意,这仅在通过 onbeforeunload 属性(而不是通过 addEventListener() 方法)附加函数时有效。此行为在 Firefox、Safari 和 Chrome 的现代版本中是一致的。

最后两种机制是传统功能;最佳做法是通过在事件对象上调用 preventDefault() 来触发对话框,同时还设置 returnValue 来支持传统情况。

语法

在诸如 addEventListener() 之类的方法中使用事件名称,或设置事件处理程序属性。

js
addEventListener("beforeunload", (event) => {});
onbeforeunload = (event) => {};

事件类型

BeforeUnloadEvent。继承自 Event

使用说明

要触发用户关闭或导航标签时显示的对话框,beforeunload 事件处理程序函数应在事件对象上调用 preventDefault()。您应该注意,现代实现

  • 要求 粘性激活 才能显示对话框。换句话说,浏览器仅在框架或任何嵌入式框架收到用户手势或用户交互时才会显示对话框。如果用户从未与页面交互,则没有用户数据要保存,因此没有对话框的合法用例。
  • 在显示的对话框中仅显示浏览器指定的通用字符串。网页代码无法控制这一点。

beforeunload 事件存在一些问题

  • 它不能可靠地触发,尤其是在移动平台上。例如,在以下情况下,beforeunload 事件根本不会触发
    1. 移动用户访问您的页面。
    2. 然后用户切换到不同的应用程序。
    3. 稍后,用户从应用程序管理器中关闭浏览器。

    注意:建议使用 visibilitychange 事件作为更可靠的信号,用于自动应用程序状态保存,以解决上述问题。有关更多详细信息,请参阅 Don't lose user and app state, use Page Visibility

  • 在 Firefox 中,beforeunload后退/前进缓存 (bfcache) 不兼容:也就是说,如果页面具有 beforeunload 侦听器,Firefox 不会将页面放入 bfcache 中,这会影响性能。

因此建议开发人员仅在用户有未保存的更改时侦听 beforeunload,以便可以使用上面提到的对话框警告他们即将发生的数据丢失,并在不再需要时再次删除侦听器。谨慎侦听 beforeunload 可以最大程度地减少对性能的影响。

事件处理程序别名

除了 Window 接口之外,事件处理程序属性 onbeforeunload 也在以下目标上可用

示例

在以下示例中,我们有一个 HTML 文本 <input> 来表示一些可能已更改并需要保存的数据

html
<form>
  <input type="text" name="name" id="name" />
</form>

我们的 JavaScript 将一个 input 事件侦听器附加到 <input> 元素,该侦听器侦听输入值的更改。当值更新为非空值时,beforeunload 事件侦听器将附加到 Window 对象。

如果值再次变为空字符串(即值被删除),beforeunload 事件侦听器将再次删除 - 如上面 使用说明 中所述,当没有未保存的数据需要警告时,应该删除侦听器。

beforeunload 事件处理程序函数调用 event.preventDefault(),当用户关闭或导航标签时触发警告对话框。我们还在处理程序函数中包含了 event.returnValue = true,以便任何不支持 event.preventDefault() 机制的浏览器仍然可以正确运行演示。

js
const beforeUnloadHandler = (event) => {
  // Recommended
  event.preventDefault();

  // Included for legacy support, e.g. Chrome/Edge < 119
  event.returnValue = true;
};

const nameInput = document.querySelector("#name");

nameInput.addEventListener("input", (event) => {
  if (event.target.value !== "") {
    window.addEventListener("beforeunload", beforeUnloadHandler);
  } else {
    window.removeEventListener("beforeunload", beforeUnloadHandler);
  }
});

<input> 值为非空值时,如果您尝试关闭、导航或重新加载页面,浏览器将显示警告对话框。试试看

规范

规范
HTML 标准
# event-beforeunload
HTML 标准
# handler-window-onbeforeunload

浏览器兼容性

BCD 表格仅在浏览器中加载

另请参阅