Page Visibility

From HTML5 Chinese Interest Group Wiki
Jump to: navigation, search

介绍

本章节为非正式内容

页面可见性规范定义了一个 Web 开发者通过程序决定页面的可见性并在其可见性发生改变的时候发出通知。在这些网页的可见性状态不得而知的过去,Web 开发者只能假设页面是始终可见的。这不仅仅对资源的浪费,同时也没有办法使得网页在运行时针对是否对用户可见而作出决定。有了网页可见性的支持,我们就可以针对网页是否可见,来优化用户体验,节约能耗。

利用这些接口,Web 应用可以基于他们是否对用户可见而选择不同的行为。比如它可以让网页在看不见的时候缩减工作。如果一个基于 Web 的邮件客户端处于可见的状态,它可以每隔几秒就检查一次新邮件。而当它不可见的时候,这个时间间隔可以自动变成几分钟检查一次。再比如它也可以用来提供和电源管理无关的更好的运行时用户体验。比如一款游戏可以在不可见的时候自动暂停。再说远一些,它可以令广告商在页面对用户不可见时不收广告取费用。

举个例子,下面的这段脚本展示了一个理想化的 Web 邮件客户端不基于网页可见性的定期查收新邮件的逻辑:
<!DOCTYPE html>
<html>
 <head>
  <script>
   var timer = 0;
   var PERIOD = 1000;

   function onLoad() {
       timer = setInterval(checkEmail, PERIOD);
   }

   function checkEmail() { 
       // Check server for new messages
   }

  </script>
 </head>
 <body onload="onLoad()">
 </body>
</html>

这段脚本每秒都会去检查新邮件,甚至在用户根本不看这个页面的时候。这是一个弱资源管理的例子。

利用 Document 接口的 hidden 特性和 visibilitychange 事件,页面可以在不可见状态下把检查新邮件的频度改为每分钟检查一次。

下面这段脚本就展示了一个理想化的 Web 邮件客户端在其可见时每秒查收新邮件、不可见时每分钟查收新邮件的逻辑:
<!DOCTYPE html>
<html>
 <head>
  <script>
   var timer = 0;
   var PERIOD_VISIBLE = 1000;
   var PERIOD_NOT_VISIBLE = 60000;

   function onLoad() {
       timer = setInterval(checkEmail, (document.hidden) ? PERIOD_NOT_VISIBLE : PERIOD_VISIBLE);
       if(document.addEventListener) document.addEventListener("visibilitychange", visibilityChanged);
   }

   function visibilityChanged() {
       clearTimeout(timer);
       timer = setInterval(checkEmail, (document.hidden) ? PERIOD_NOT_VISIBLE : PERIOD_VISIBLE);
   }

   function checkEmail() { 
       // Check server for new messages
   }

  </script>
 </head>
 <body onload="onLoad()">
 </body>
</html>

一致性要求

(略)

术语

有的时候 Foo 是一个实际的接口,我们说“一个 Foo 对象”,实际是指“一个用接口 Foo 实现的对象”。

页面可见性

介绍

本章节是非正式的。

本规范介绍了一个提供给 Web 应用针对当前页面的可见性及其状态变化进行编程的接口。

document 接口的扩展

HTML5 规范定义了一部分 Document 接口,本规范对其进行了扩展:
enum VisibilityState { "hidden", "visible", "prerender", "unloaded" };

partial interface Document {
  readonly attribute boolean hidden;
  readonly attribute VisibilityState visibilityState; 
};

hidden 特性

在对 hidden 特性进行读取时,如果被顶级浏览上下文包含的 Document 是不可见的,则必须返回 true。如果被顶级浏览上下文包含的 Document 在屏幕的任何位置可见,则都必须返回 false。

如果 Document 的 defaultView 是 null,则在读取时,hidden 特性必须返回 true。

考虑到有辅助工具出现在全屏显示一个页面上的情况,该特性在用户代理并未最小化但被其它程序完全遮挡的时候可以返回 false。

注:比如,hidden 特性在读取时的返回值,在以下情况为 true:
  • 用户代理被最小化
  • 用户代理并未最小化,但是页面在后台标签
  • 用户代理正在关闭的页面
  • 用户代理正在转为一条会话历史记录
  • 操作系统被锁屏

相反的,以下情况为 false:

  • 用户代理并未最小化且页面是最前面的那个标签
  • 用户代理完全被一个辅助工具遮挡,比如放大镜,但是页面试图是显示出来的

visibilityState 特性

对在 visibilityState 特性进行读取时,必须返回下面几个 DOMString 中的一个值。这些值还可以带“厂商前缀”中定义的前缀。

  • hidden
  • visible
  • prerender
  • unloaded

hidden

在读取 visibilityState 特性值的时候,如果被包含在顶级浏览上下文中的 Document 在屏幕上任何地方都不可见,则必须返回 DOMString hidden

在读取 visibilityState 特性值的时候,如果 Document 的 defaultView 是 null,则必须返回 DOMString hidden

考虑到有辅助工具出现在全屏显示一个页面上的情况,visibilityState 特性在用户代理并未最小化但被其它程序完全遮挡的时候可以返回 DOMString visible 而不是 DOMString hidden

注:比如,visibilityState 特性在读取时的返回值,在以下情况为 DOMString hidden
  • 用户代理被最小化
  • 用户代理并未最小化,但是页面在后台标签
  • 操作系统被锁屏

visible

在读取 visibilityState 特性值的时候,如果被包含在顶级浏览上下文中的 Document 在屏幕上至少任一地方可见,则必须返回 DOMString visible。这也和 hidden 特性取值为 false 时是同等情况。

考虑到有辅助工具出现在全屏显示一个页面上的情况,visibilityState 特性在用户代理并未最小化但被其它程序完全遮挡的时候可以返回 DOMString visible

prerender

在读取 visibilityState 特性值的时候,如果被包含在顶级浏览上下文中的 Document 在屏幕外并不可见,则可以返回 DOMString prerender。这个返回值对于用户代理来说是可选支持的。

unloaded

在读取 visibilityState 特性值的时候,如果被包含在顶级浏览上下文中的 Document 正在关闭,则应该返回 DOMString unloaded。这个返回值对于用户代理来说是可选支持的。

visibilitychange事件

用户代理必须在其确定被顶级浏览上下文包含的 Document 的可见性发生了变化之后,触发 visibilitychange 事件。

过程模型

当用户代理确定被包含在顶级浏览上下文内的 Document 的可见性发生改变,则必须允许下面的步骤:

如果被包含在顶级浏览上下文内的 Document 现在至少有部分在屏幕上可见,则:

  1. 如果转为会话历史记录,则在运行 pageshow 事件的步骤之前运行当前可见算法
  2. 否则,触发一个任务来运行当前可见算法

否则如果被包含的顶级浏览上下文内的 Document 现在并不可见或正在关闭,则

  1. 如果用户代理正在关闭该 Document,则在关闭文档时可见性改变步骤的同时运行当前隐藏算法
  2. 否则,触发一个任务来允许当前隐藏算法

当前可见算法为同步执行下面几个步骤:

  1. 设置 hidden 特性为 false
  2. 设置 visibilityState 特性为 visible
  3. 触发一个简单的事件,名为 visibilitychange,冒泡,但不可取消,且在 Document 上没有默认动作

当前隐藏算法为同步执行下面几个步骤:

  1. 设置 hidden 特性为 true
  2. 设置 visibilityState 特性为 hidden。如果用户代理正在关闭 Document,则可以可选的设置 visibilityState 特性为 unloadedhidden
  3. 触发一个简单的事件,名为 visibilitychange,冒泡,但不可取消,且在 Document 上没有默认动作

厂商前缀

我们不鼓励厂商自定义专属的用户代理扩展。如果实在需要,比如出于试验的目的,厂商必须使用下面的扩展机制:

如果一个 visibilityState 特性的扩展返回值需要一个试验性的可见性状态,用户代理必须在 VisibilityState 中更新枚举一个 DOMString 类型的值,形如:

[厂商前缀]-[名称]

其中,

  • [厂商前缀] 是一个非大写开头的厂商标识符
  • [名称] 是一个费大些开头的确定的可见性状态名称
  • 并且上述名称都在 ACSII 字符集内

隐私

页面可见性的 API 可用允许网页的第三方内容判断顶级浏览上下文包含的 Document 的可用性。它与已有的其它机制,如 focusblur 事件相比之下,精度更高。尽管如此,从实践的角度考虑,这样的信息曝光度并不强烈。

引用

[IETF RFC 2119]

Key words for use in RFCs to Indicate Requirement Levels, Scott Bradner, Author. Internet Engineering Task Force, March 1997. Available at http://www.ietf.org/rfc/rfc2119.txt.

[HTML5]

HTML5, Robin Berjon et al., Editors. World Wide Web Consortium, December 2012. This version of the HTML5 is available from http://www.w3.org/TR/html5/. The latest editor's draft of HTML5 is available at http://www.w3.org/html/wg/drafts/html/CR/.

[Web IDL]

Web IDL, Cameron McCormack, Editor. World Wide Web Consortium, April 2012. This version of the Web IDL specification is available from http://www.w3.org/TR/2012/CR-WebIDL-20120419/. The latest version of Web IDL is available at http://www.w3.org/TR/WebIDL/.

原版致谢

We would like to sincerely thank Karen Anderson, Nic Jansma, Alex Komoroske, Cameron McCormack, James Robinson, Jonas Sicking, Kyle Simpson, Jason Weber, and Boris Zbarsky to acknowledge their contributions to this work.