使用 Page Visibility API

Ernest Delgado
Ernest Delgado

简介

作为 Web 开发者,我们往往会为那些能让我们创建更具吸引力、更具互动性的网页的新技术而感到兴奋。使用 WebGL 呈现 3D 图形?当然可以。通过 WebAudio 实现高级音频功能?没问题。使用网络摄像头和麦克风的实时协作应用?我要注册!

同样重要的是,这些技术让我们能够构建运行效率更高、整体用户体验更好的应用。这时,PageVisibility 等 API 就可以派上用场了。

Page Visibility API 可执行一项简单但重要的功能,即让您的应用知道网页何时对用户可见。有了这项基本信息,您就可以创建在未被查看时表现不同的网页。请参考以下示例:

  • 从服务器检索信息的网页在未被主动查看时可以减慢其更新周期
  • 显示轮播图片或视频/音频内容的页面可以暂停,直到用户再次显示该页面
  • 应用可以决定仅在隐藏视图时向用户显示通知

起初,除了方便用户之外,此 API 似乎没有太大用处,但考虑到移动网络浏览量的大幅增加,任何有助于节省设备电池电量的功能都变得非常重要。通过使用 PageVisibility API,您的网站可以帮助用户的设备降低功耗并延长续航时间。

Browser Support

  • Chrome: 33.
  • Edge: 12.
  • Firefox: 18.
  • Safari: 7.

Source

API 规范(在撰写本文时处于候选推荐阶段)提供了用于检测文档可见性状态的属性,以及用于响应可见性变化的事件。

在本教程中,我将介绍该 API 的基础知识,并展示如何将其应用于一些实际示例(如果您是急性子,可以随时跳到这些示例)。

文档公开范围属性

当前版本的 PageVisibilityAPI 规范定义了两个文档属性:布尔值 hidden 和枚举 visibilityState。visibilityState 属性目前有四个可能的值:hidden、visible、prerender 和 unloaded。

正如您所料,当文档完全不可见时,hidden 属性会返回 true。通常,这意味着文档处于最小化状态、位于后台标签页中、操作系统的锁屏界面已打开等。如果文档的任何部分在至少一个显示屏上至少部分可见,则该属性会设置为 false。此外,为了适应无障碍工具,当屏幕放大镜等工具完全遮挡文档但显示其视图时,可以将 hidden 属性设置为 false。

处理供应商前缀

为了将重点放在代码上,而不是所有特定于供应商的前缀上,我将使用一些辅助函数来隔离特定于浏览器的内容。一旦您不再支持 Android 4.4 浏览器,就可以移除此部分并继续使用标准名称。

function getHiddenProp(){
    var prefixes = ['webkit','moz','ms','o'];

    // if 'hidden' is natively supported just return it
    if ('hidden' in document) return 'hidden';

    // otherwise loop over all the known prefixes until we find one
    for (var i = 0; i < prefixes.length; i++){
        if ((prefixes[i] + 'Hidden') in document)
            return prefixes[i] + 'Hidden';
    }

    // otherwise it's not supported
    return null;
}

文档属性示例

现在,我们可以编写一个跨浏览器函数 isHidden(),以查看文档是否可见。

function isHidden() {
    var prop = getHiddenProp();
    if (!prop) return false;

    return document[prop];
}

如需更精细地查看文档的可见性,您可以使用 visibilityState 属性。此属性会返回以下四个值之一:

  • hidden:文档完全隐藏,无法查看
  • visible:文档至少在一部显示设备上至少部分可见
  • prerender:文档在屏幕外加载且不可见(此值是可选的;并非所有浏览器都支持此值)
  • unloaded:如果要卸载文档,则会返回此值(此值是可选的;并非所有浏览器都支持此值)

VisibilityChange 事件

除了可见性属性之外,还有一个 visibilitychange 事件,每当文档的可见性状态发生变化时,该事件就会触发。您可以直接在文档对象上为此事件注册事件监听器:

活动示例

// use the property name to generate the prefixed event name
var visProp = getHiddenProp();
if (visProp) {
  var evtname = visProp.replace(/[H|h]idden/,'') + 'visibilitychange';
  document.addEventListener(evtname, visChange);
}

function visChange() {
   var txtFld = document.getElementById('visChangeText');

   if (txtFld) {
      if (isHidden())
         txtFld.value += "Tab Hidden!\n";
      else
         txtFld.value += "Tab Visible!\n";
   }
}

摘要

构建出色的 Web 应用不仅仅是使用用户可以看到并与之互动的炫酷、引人注目的功能。真正出色的应用会充分考虑用户的资源和注意力,而 Page Visibility API 是实现这一目标的重要一环。如需详细了解如何构建资源感知型 Web 应用,请参阅其他与性能相关的文章。

外部引用