页面可见性 API

页面可见性 API 提供事件,您可以监视这些事件以了解文档何时变得可见或隐藏,以及查看页面当前可见性状态的功能。

这对于节省资源和提高性能特别有用,因为它可以让页面在文档不可见时避免执行不必要的任务。

概念和用法

当用户最小化窗口、切换到另一个选项卡或文档被另一个窗口完全遮挡时,API 会发送一个 visibilitychange 事件以告知监听器页面的状态已更改。您可以检测该事件并执行一些操作或以不同的方式运行。例如,如果您的 Web 应用程序正在播放视频,它可以在用户将选项卡置于后台时暂停视频,并在用户返回选项卡时恢复播放。用户不会失去视频中的位置,视频的音轨不会干扰新前台选项卡中的音频,并且用户在此期间不会错过任何视频内容。

<iframe> 的可见性状态与父文档相同。使用 CSS 属性(如 display: none;)隐藏 <iframe> 不会触发可见性事件,也不会更改框架中包含的文档的状态。

用例

让我们考虑一下页面可见性 API 的一些用例。

  • 一个网站有一个图片轮播,除非用户正在查看页面,否则它不应该前进到下一张幻灯片
  • 显示信息仪表板的应用程序在页面不可见时不希望轮询服务器以获取更新
  • 一个网站希望在设备处于待机模式时关闭声音(用户按下电源按钮以关闭屏幕)

开发人员历来使用不完善的代理来检测这一点。例如,监视窗口上的 blurfocus 事件可以帮助您了解您的页面何时不是活动页面,但它不会告诉您您的页面实际上对用户隐藏了。页面可见性 API 解决了这个问题。

注意:虽然 onbluronfocus 会告诉您用户是否切换了窗口,但这并不一定意味着它被隐藏了。页面只有在用户切换选项卡或最小化包含该选项卡的浏览器窗口时才会被隐藏。

旨在帮助后台页面性能的策略

除了页面可见性 API 之外,用户代理通常还会实施一些策略来减轻后台或隐藏选项卡的性能影响。这些可能包括

  • 大多数浏览器停止将 requestAnimationFrame() 回调发送到后台选项卡或隐藏的 <iframe>,以提高性能和延长电池寿命。
  • 后台/非活动选项卡中的计时器(如 setTimeout())会被限制,以帮助提高性能。有关更多详细信息,请参阅 指定延迟时间更长的原因
  • 浏览器实施基于预算的后台超时限制。这种机制在现代浏览器中以类似的方式运行,详细信息如下
    • 在 Firefox 中,后台选项卡中的每个窗口都有自己的时间预算(以毫秒为单位)——最大值和最小值分别为 +50 毫秒和 -150 毫秒。Chrome 非常相似,只是预算以秒为单位。
    • 窗口在 30 秒后会受到限制,并采用与为窗口计时器指定的相同限制延迟规则(再次查看 指定延迟时间更长的原因)。在 Chrome 中,此值为 10 秒。
    • 只有在预算为非负数时才允许计时器任务。
    • 计时器代码执行完毕后,执行所需的时间将从其窗口的超时预算中减去。
    • 预算在 Firefox 和 Chrome 中都以每秒 10 毫秒的速度再生。

某些进程不受此限制行为的影响。在这些情况下,您可以使用页面可见性 API 在选项卡隐藏时降低其性能影响。

  • 正在播放音频的选项卡被视为前台,不会受到限制。
  • 运行使用实时网络连接的代码的选项卡(WebSocketWebRTC)不会受到限制,以避免这些连接超时并意外关闭。
  • IndexedDB 进程也不会受到限制,以避免超时。

对其他接口的扩展

实例属性

页面可见性 API 向 Document 接口添加了以下属性

Document.hidden 只读

如果页面处于对用户隐藏的状态,则返回 true,否则返回 false

Document.visibilityState 只读

指示文档当前可见性状态的字符串。可能的值包括

可见

页面内容可能至少部分可见。在实践中,这意味着页面是非最小化窗口的前台选项卡。

隐藏

页面内容对用户不可见,可能是由于文档的选项卡处于后台或属于最小化窗口的一部分,也可能是由于设备的屏幕已关闭。

事件

页面可见性 API 向 Document 接口添加了以下事件

visibilitychange

当选项卡的内容变得可见或被隐藏时触发。

示例

在页面隐藏时暂停音频

此示例在页面隐藏时暂停播放音频,并在页面再次变得可见时恢复播放。<audio> 元素控件允许用户在播放和暂停音频之间切换。布尔值 playingOnHide 用于防止音频在页面更改为 visible 状态时播放,但媒体在页面隐藏时没有播放。

HTML

html
<audio
  controls
  src="https://mdn.github.io/webaudio-examples/audio-basics/outfoxing.mp3"></audio>

JavaScript

js
const audio = document.querySelector("audio");

let playingOnHide = false;

document.addEventListener("visibilitychange", () => {
  if (document.hidden) {
    playingOnHide = !audio.paused;
    audio.pause();
  } else {
    // Page became visible! Resume playing if audio was "playing on hide"
    if (playingOnHide) {
      audio.play();
    }
  }
});

结果

规范

规范
HTML 标准
# dom-document-visibilitystate

浏览器兼容性

BCD 表仅在浏览器中加载

另请参阅