使用 Page Visibility API

欧内斯特·德尔加多
欧内斯特·德尔加多

简介

作为 Web 开发者,我们往往会对能够让我们创建更具吸引力、互动性的网页的新技术感到兴奋。使用 WebGL 制作 3D 图形吗?当然可以。WebAudio 的高级音频功能?没关系。要使用网络摄像头和麦克风进行实时协作应用程序吗?我要注册!

一些技术虽然不那么令人兴奋,但也同样重要,正是有了这些技术,我们能够更高效运行、更出色地改善整体用户体验。这正是 PageVisibility 等 API 的用武之地。

Page Visibility API 执行一项简单但重要的功能,它让您的应用知道网页何时对用户可见。通过这项基本信息,您可以制作在用户未查看时行为方式会有所不同的网页。请参考以下示例:

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

乍看之下,除了用户便利之外,此 API 似乎没什么用处,但考虑到移动网络浏览量的迅猛增长,任何有助于节省设备电池电量的措施都变得非常重要。通过使用 PageVisibility API,您的网站可以帮助用户的设备消耗更少的电量并延长使用寿命。

浏览器支持

  • 33
  • 12
  • 18
  • 7

来源

该 API 规范在撰写本文时处于“候选建议”阶段,它既提供了用于检测文档的可见性状态的属性,又提供了用于响应可见性变更的事件。

在本教程中,我将介绍 API 的基础知识,并展示如何将其应用到一些实际示例中(如果您缺乏耐心,可以跳过这些示例)。

文档公开范围属性

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

正如您所预期的,当文档完全不可见时,隐藏属性会返回 true。通常情况下,这意味着文档会最小化、在背景标签页上显示、操作系统的锁定屏幕打开,等等。如果文档的任何部分至少在一个显示屏上至少部分可见,则此属性设置为 false。此外,为了适应无障碍工具,当屏幕放大镜等工具会完全遮盖文档,但显示的是文档的视图时,可以将隐藏属性设置为 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 应用,请参阅其他与性能相关的文章

外部引用