这是我参与8月更文挑战的第6天,活动详情查看:8月更文挑战
前言
在Chrome
中,每一个网页标签都是一个进程,当该标签处于不可见状态一定时间后会处于休眠状态以节省内存等系统资源。我们在开发时候有时需要检测用户是否处于当前页面,以满足功能上的需求。
在以往,判断用户是否处于当前页面,通常是判断pagehide
、beforeunload
、unload
这三个事件,但是在移动端上不一定全部都会触发,因为当前页面被系统切换到另外一个应用,以及系统杀死浏览器进程,是无法监听到的。当用户切换应用,然后由于内存不足或太久未使用,系统会直接杀死浏览器进程,此时unload
,beforeunload
会来不及触发。
Page Visibility API
,不管移动端还是桌面,所有情况下,都能监听到页面的可见性发生变化。使用它可以增强用户体验,当用户不在当前页面时,可以停止音视频播放,网络请求,动画加载等,以节约资源和电量。
接口特性
Page Visibility API
的方法和属性被挂载到document
对象上,我们随时都能调用它,它具有以下属性:
document.hidden
:窗口是否不可见,只读属性,当窗口处于完全不可见时为truedocument.visibilityState
:只读属性,表示当前窗口的状态:'hidden' | 'visible' | 'prerender'
,只要当前页面有一丁点可见都为true
。visibilitychange
:事件类型,当窗口的可见性发生变化时触发。
推荐使用document.visibilityState
而不是document.hidden
,它除了能检测页面的可见性还能检测页面是否处于预渲染阶段。
document.hidden
只读属性,返回一个布尔值,表示页面是否可见,为true
时表示完全不可见。
document.visibilityState
相对于document.hidden
,document.visibilityState
能检测更复杂的场景。它有三个状态值:
hidden
:页面完全不可见。visible
:页面至少一部分可见。prerender
:页面即将或正在渲染,处于不可见状态。
prerender
状态只在支持"预渲染"的浏览器上才会出现,比如 Chrome
就有预渲染功能,可以在用户不可见的状态下,预先把页面渲染出来,等到用户要浏览的时候,直接展示渲染好的网页。
以下情况为hidden
:
- 浏览器最小化。
- 浏览器没有最小化,但是当前页面切换为其他页面。
- 浏览器将要卸载(
unload
)页面。 - 系统锁屏。
上面四种场景涵盖了页面可能被卸载的所有情况。除了hidden
和prerender
,其他时候只要有一点页面显示都为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;
),并不会影响内嵌页面的可见性。
使用场景
节省音频流量
当用户离开当前页面时,我们可以暂停音视频的播放,以节省用户的流量。
<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
轮询,停止页面动画特效等等,这些都能进一步提高页面的性能和用户体验。
总结
目前该接口得到广泛的支持,web性能工作组织(Web Performance Working Group
)也提倡我们在构建应用时使用该API
来提升提升应用性能和用户体验。
参考
- 页面可见性 API - Web API 接口参考 | MDN (mozilla.org)
- Page Visibility Level 2 (w3.org)
- Using the PageVisibility API - HTML5 Rocks
- How to Detect Idle Browser Tabs with the Page Visibility API (alligator.io)
- Code Splitting | webpack
往期文章
- 更强大的文件接口,File System Access API|8月更文挑战 (juejin.cn)
- 什么,网页也能直接与硬件通信?Web Serial API!|8月更文挑战 (juejin.cn)
- 5000字带你全面深入理解JS中的Stream API|8月更文挑战 (juejin.cn)
- 现阶段web与外围硬件交互的接口概述 (juejin.cn)
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!