使用Page Visibility API来提升页面性能和用户体验

这是我参与8月更文挑战的第6天,活动详情查看:8月更文挑战html

前言

Chrome中,每个网页标签都是一个进程,当该标签处于不可见状态必定时间后会处于休眠状态以节省内存等系统资源。咱们在开发时候有时须要检测用户是否处于当前页面,以知足功能上的需求。html5

在以往,判断用户是否处于当前页面,一般是判断pagehidebeforeunloadunload这三个事件,可是在移动端上不必定所有都会触发,由于当前页面被系统切换到另一个应用,以及系统杀死浏览器进程,是没法监听到的。当用户切换应用,而后因为内存不足或过久未使用,系统会直接杀死浏览器进程,此时unloadbeforeunload会来不及触发。webpack

Page Visibility API,无论移动端仍是桌面,全部状况下,都能监听到页面的可见性发生变化。使用它能够加强用户体验,当用户不在当前页面时,能够中止音视频播放,网络请求,动画加载等,以节约资源和电量。web

接口特性

Page Visibility API的方法和属性被挂载到document对象上,咱们随时都能调用它,它具备如下属性:api

  • document.hidden:窗口是否不可见,只读属性,当窗口处于彻底不可见时为true
  • document.visibilityState:只读属性,表示当前窗口的状态: 'hidden' | 'visible' | 'prerender',只要当前页面有一丁点可见都为true
  • visibilitychange:事件类型,当窗口的可见性发生变化时触发。

推荐使用document.visibilityState而不是document.hidden,它除了能检测页面的可见性还能检测页面是否处于预渲染阶段。浏览器

document.hidden

只读属性,返回一个布尔值,表示页面是否可见,为true时表示彻底不可见。缓存

document.visibilityState

相对于document.hiddendocument.visibilityState能检测更复杂的场景。它有三个状态值:markdown

  • hidden:页面彻底不可见。
  • visible:页面至少一部分可见。
  • prerender:页面即将或正在渲染,处于不可见状态。

prerender状态只在支持"预渲染"的浏览器上才会出现,好比 Chrome 就有预渲染功能,能够在用户不可见的状态下,预先把页面渲染出来,等到用户要浏览的时候,直接展现渲染好的网页。网络

如下状况为hidden:app

  • 浏览器最小化。
  • 浏览器没有最小化,可是当前页面切换为其余页面。
  • 浏览器将要卸载(unload)页面。
  • 系统锁屏。

上面四种场景涵盖了页面可能被卸载的全部状况。除了hiddenprerender,其余时候只要有一点页面显示都为visible

页面卸载以前,document.visibilityState必定会变成hidden状态,这也是W3C设计这个API的主要目的。

visibilitychange

只要document.visibilityState属性发生变化,就会触发visibilitychange事件。所以,能够经过监听这个事件来检测页面可见性的变化。

document.addEventListener("visibilitychange",()=>{
   if(document.visibilityState==="hidden"){
       console.log("页面不可见")
   }
   else{
       console.log("页面可见")
   }
})
复制代码

document.visibilityState属性只针对顶层窗口,内嵌的<iframe>页面的document.visibilityState属性由顶层窗口决定。使用 CSS 属性隐藏<iframe>页面(好比display: none;),并不会影响内嵌页面的可见性。

MDN的描述:

<iframe>的可见性状态与父文档相同。使用CSS属性(例如display: none;)隐藏<iframe>不会触发可见性事件或更改框架中包含的文档的状态。

使用场景

节省音频流量

当用户离开当前页面时,咱们能够暂停音视频的播放,以节省用户的流量。

<video id="video">
  <source id='mp4' src="movie.mp4" type='video/mp4'/>
</video>
复制代码
const onVisibilityChange = () => {
  const video = document.getElementById("video");
  // 页面彻底不可见时,暂停播放,可见时则恢复播放
  return document.hidden
    ? video.pause()
    : video.play();
}

document.addEventListener("visibilitychange", onVisibilityChange);
复制代码

一个栗子: Demo: Page Visibility API (daniemon.com)

资源懒加载

除了节省流量,咱们也能够结合webpack的动态加载模块import()实现资源的懒加载。例如,当用户离开当前页面,咱们能够请求用户接下来可能用到的资源并缓存起来,以提升使用体验。

let loaded = false;
const onVisibilityChange = () => {
  if (!loaded && document.visibilityState === 'visible') {
    Promise.all([
      import(/* webpackChunkName: "bundle-[index]"*/ './dist'),
      import(/* webpackPrefetch: 0 */ './images')
    ]).then(() => {
      loaded = true;
    });
  }
};

document.addEventListener('visibilitychange', onVisibilityChange);
复制代码

其余

除了上面提到的场景外,咱们还能用来关闭定时器,挂起webSocket轮询,中止页面动画特效等等,这些都能进一步提升页面的性能和用户体验。

总结

image.png

目前该接口获得普遍的支持,web性能工做组织Web Performance Working Group)也提倡咱们在构建应用时使用该API来提高提高应用性能和用户体验。

参考

往期文章

相关文章
相关标签/搜索