页面可见状态API使用方法

Page Visibility API用于获取当前页面的可见性状态,在音频、视频播放、游戏等场景中十分有用。

本文Demo请见:https://www.lyz810.com/demo/pageVisibility/
一、应用场景

页面可见性状态一般可以用于以下场景:

  1. 音频或视频(尤其是视频)播放时,当页面不可见自动暂停播放,页面恢复后再继续播放
  2. 一些定时执行的操作(如微博获取最新的微博条数,该动作每分钟获取一次),没有必要在用户不可见的时候去获取数据
  3. 网页游戏在用户切换页面后,游戏自动暂停,用户体验更好
  4. 统计用户停留时长,这种方式比目前常用的两次页面打开时间之差得到用户停留时长更准确

二、document.visibilityState属性值

document.visibilityState有四个值(后两个是可选属性,浏览器可以不实现):

  1. hidden
  2. visible
  3. prerender
  4. unloaded

以下情况,document.visibilityState的值为hidden:

  • 浏览器最小化
  • 浏览器没有最小化,但是页面是非活动的标签页(即切换到其他标签),浏览器被其他窗口覆盖值不会受影响
  • 操作系统锁屏

在页面可见时,值为visible

在页面的父级页面不可见时,值可以为prerender(该属性为可选的)

在文档卸载时,值应为unloaded(该属性为可选的)

三、document.hidden属性

document.hidden为布尔型,当页面不可见(hidden)时为true,可见(visible)时为false

四、visibilitychange事件

document中的visibilitychange用于监听可见状态改变的事件,用法如下:

document.addEventListener('visibilitychange', function(){
  console.log(document.visibilityState);
}, false);

五、兼容性

IE:10+
FireFox:18+(10~17需要加moz前缀)
Chrome:33+(14~32需要加webkit前缀)
Safari:6.1+
Opera:12.1以及20+(15~19需要加webkit前缀,12.1不需要加前缀)

Beacon API介绍

Beacon API可以向指定服务器发送少量的数据以实现统计等目的。

一、应用场景

主要用于记录并发送用户行为、发送错误日志等。
之前记录用户行为通常是通过发送一个GET请求(一般是一个带所有统计信息参数的图片请求),使统计服务器获取到用户行为数据并记录。
这种方式有以下几个弊端:
1.当页面关闭时,发送的统计请求可能不会成功,导致统计数据丢失
2.通常为了解决关闭页面的统计数据丢失问题,会发起一个同步的请求,这样会阻塞页面的卸载
3.GET请求通常有长度限制,可携带的数据量有限,并且一般只能携带文本信息
而使用Beacon API后,上述问题都能够解决:
Beacon是以非阻塞POST的方式发送数据,支持多种数据类型:ArrayBufferView, Blob, DOMString, 或者 FormData 类型的数据
关闭页面不会中断Beacon的发送,也不会阻塞页面的卸载,用户体验更好

二、API用法

navigator.sendBeacon(url, data);
url 参数表明 data 将要被发送到的网络地址。(不存在跨域问题,但https的页面中不能向http协议的统计服务器发送数据,会报安全错误)
data 参数是将要发送的 ArrayBufferView, Blob, DOMString, 或者 FormData 类型的数据。
sendBeacon() 方法返回 true 如果用户代理能够成功地将要发送的数据排入队列,否则返回 false。
示例:

document.getElementById('container').addEventListener('click', function(e){
   if(e.target.tagName === 'A'){
      var formData = new FormData();
      formData.append('type', 'click');
      formData.append('elementType', 'link');
      formData.append('href', e.target.href);
      formData.append('t', Date.now());
      navigator.sendBeacon('http://tongji.example.com', formData);
   }
}, false);

window.addEventListener('unload', function(){
    var data = JSON.stringify({
        type: 'unload',
        t: Date.now()
      });
    navigator.sendBeacon('http://tongji.example.com', data);
}, false);

上面示例中,为container下的所有A标签的点击事件进行了统计,当点击链接时,会发送统计信息到统计服务器tongji.example.com上,并以form表单的形式发送。
在页面卸载时,也会将相关信息以json字符串的方式发送给统计服务器
注意此例为了演示不同的发送方式采用了两种不同的数据类型,实际使用时建议同一使用一种数据类型便于统计处理。

三、兼容性

IE:不支持
Edge:14+
Firefox:31+
Chrome:39+
Opera:26+

四、注意事项

该API没有响应回调方法,所以建议服务器返回204状态码
该API同样可以应用于一些只需要发送数据而不需要关心返回结果的场景(如CSRF攻击中使用此API构造POST请求,要比模拟表单提交成本低很多)