Window:beforeunload 事件

可用性有限

此特性不是基线特性,因为它在一些最广泛使用的浏览器中不起作用。

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

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

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

  • 调用事件对象的 preventDefault() 方法。
  • 将事件对象的 returnValue 属性设置为非空字符串值或任何其他 真值
  • 从事件处理函数返回任何真值,例如 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 事件作为更可靠的自动应用程序状态保存信号,以避免上述问题。有关详细信息,请参阅 不要丢失用户和应用程序状态,使用页面可见性

  • 在 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

浏览器兼容性

另见