当一个网页是可见或点击选中的状态时 Page Visibility API 可以让你获取到这种状态。在用户使用切换标签的方式来浏览网页时,非常合理的情况是任何在后台页面都不会展示给用户。 当用户最小化网页或者浏览到其他标签的网页时,API将发送一个关于当前页面的可见信息的事件visibilitychange。你可以检测该事件然后执行一些活动或是展示不同的效果。比如,如果你的网站app正在播放一个视频,也许当用户浏览其他浏览器时它可以暂停,那么当用户切换回来的时候,就可以继续播放了。用户可以继续观看,不会因为浏览其他的浏览器导致丢失当前视频的进度。

9550b1d94bf9b902dee30756ab1741d2

好处

这个API在节约资源上是非常有用的,当网页不可见时,这个API通过提供给开发者可以操作不必须的任务的接口。

使用情景

一些例子:

  • 网站有图片轮播效果,只有在用户观看轮播的时候,才会自动展示下一张幻灯片。
  • 显示信息仪表盘的应用程序不希望在页面不可见时轮询服务器进行更新。
  • 页面想要检测是否正在渲染,以便可以准确的计算网页浏览量
  • 当设备进入待机模式时,网站想要关闭设备声音(用户按下电源键关闭屏幕)

开发者在过去使用不完善的代理来处理这一点。比如, 当你的页面不处于活动状态时,在window上声明一个 onblur/onfocus 处理器来帮助你了解页面不是活动状态,但是它并没有告诉你页面是对用户隐藏的。The Page Visibility API 解决了这个问题。(在和window上声明 onblur/onfocus 处理器这种方式相比,关键不同在于当另一个页面处于激活状态并且浏览器窗口丢失了焦点时,页面不会隐藏。 页面只有在用户切换到其他标签或最小化窗口时,才会被隐藏。)

在此例中,当你切换到另一个标签时视频会暂停,当你返回到当前标签时视频会再次播放,代码如下:

// 设置隐藏属性和改变可见属性的事件的名称
var hidden, visibilityChange; 
if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support 
  hidden = "hidden";
  visibilityChange = "visibilitychange";
} else if (typeof document.msHidden !== "undefined") {
  hidden = "msHidden";
  visibilityChange = "msvisibilitychange";
} else if (typeof document.webkitHidden !== "undefined") {
  hidden = "webkitHidden";
  visibilityChange = "webkitvisibilitychange";
}
 
var videoElement = document.getElementById("videoElement");

// 如果页面是隐藏状态,则暂停视频
// 如果页面是展示状态,则播放视频
function handleVisibilityChange() {
  if (document[hidden]) {
    videoElement.pause();
  } else {
    videoElement.play();
  }
}

// 如果浏览器不支持addEventListener 或 Page Visibility API 给出警告
if (typeof document.addEventListener === "undefined" || typeof document[hidden] === "undefined") {
  console.log("This demo requires a browser, such as Google Chrome or Firefox, that supports the Page Visibility API.");
} else {
  // 处理页面可见属性的改变
  document.addEventListener(visibilityChange, handleVisibilityChange, false);
    
  // 当视频暂停,设置title
  // This shows the paused
  videoElement.addEventListener("pause", function(){
    document.title = 'Paused';
  }, false);
    
  // 当视频播放,设置title
  videoElement.addEventListener("play", function(){
    document.title = 'Playing'; 
  }, false);

}


属性

document.hidden Read only

如果页面处于被认为是对用户隐藏状态时返回true,否则返回false。

document.visibilityState Read only

是一个用来展示文档可见性状态的字符串。可能的值:

  • visible : 页面内容至少是部分可见。 在实际中,这意味着页面是非最小化窗口的前景选项卡。
  • hidden : 页面内容对用户不可见。 在实际中,这意味着文档可以是一个后台标签,或是最小化窗口的一部分,或是在操作系统锁屏激活的状态下。
  • prerender : 页面内容正在被预渲染且对用户是不可见的(被document.hidden当做隐藏). 文档可能初始状态为prerender,但绝不会从其它值转为该值。 注释:浏览器支持是可选的。
  • unloaded : 页面正在从内存中卸载。 注释:浏览器支持是可选的。

通过document.hidden属性,可判断页面是否可见。 如果不可见,则document.hidden为true. 如果可见, 则为false。

但是, 如果该页面只是被其它窗口挡住, 而非最小化该页面。 则document.hidden仍然是false. 而不是不可见。

//startSimulation 和 pauseSimulation 在其他地方定义
function handleVisibilityChange() {
  if (document.hidden) {
    pauseSimulation();
  } else  {
    startSimulation();
  }
}

document.addEventListener("visibilitychange", handleVisibilityChange, false);


标题切换

先看一个简单的例子

document.addEventListener("visibilitychange", function() {
    let title = document.title;
    if (document.hidden) {
        document.title = "出BUG了,快看!";
    } else {
        document.title = title;
    }
});

多浏览器例子


$(document).ready(function() {
    let title = document.title;
    // 设置隐藏属性和改变可见属性的事件的名称
    var hidden, visibilityChange;
    if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support 
        hidden = "hidden";
        visibilityChange = "visibilitychange";
    } else if (typeof document.msHidden !== "undefined") {
        hidden = "msHidden";
        visibilityChange = "msvisibilitychange";
    } else if (typeof document.webkitHidden !== "undefined") {
        hidden = "webkitHidden";
        visibilityChange = "webkitvisibilitychange";
    }

    // 如果浏览器不支持addEventListener 或 Page Visibility API 给出警告
    if (typeof document.addEventListener === "undefined" || typeof document[hidden] === "undefined") {
        console.log("This demo requires a browser, such as Google Chrome or Firefox, that supports the Page Visibility API.");
    } else {
        // 处理页面可见属性的改变
        document.addEventListener(visibilityChange, function() {
            console.log(title);
            if (document[hidden]) {
                document.title = "出BUG了,快看!";
            } else {
                document.title = title;
            }
        }, false);
    }
});