当前位置: 首页 > news >正文

利用 Page Visibility API 优化网页性能与用户体验

在现代 Web 开发中,用户可能会频繁切换标签页,或让网页处于后台运行。为了避免不必要的资源浪费并提升用户体验,合理利用 Page Visibility API 可以在页面不可见时暂停或减少资源的消耗,并在页面重新可见时恢复正常操作。

在这篇博客中,我将展示如何通过 Page Visibility API 实现以下场景:

  1. 当用户切换标签页时暂停视频或音频播放。
  2. 当页面不可见时停止资源密集型的动画。
  3. 页面不可见时停止 API 请求,并在页面可见时重新开始。
  4. 当用户返回页面时恢复定时操作。

什么是 Page Visibility API?

Page Visibility API 是一个浏览器提供的 API,它可以告诉我们页面的可见性状态。当页面变为不可见时,我们可以暂停一些不必要的操作,比如动画或媒体播放。这个 API 提供了两个核心功能:

  • document.hidden:返回一个布尔值,指示页面当前是否隐藏。
  • document.visibilityState:返回页面的可见性状态,可以是 'visible'(页面可见)、'hidden'(页面隐藏)或 'prerender'(页面正在预渲染)。
  • visibilitychange 事件:当页面的可见性状态(document.visibilityState)改变时触发。

visibilityState 的作用

document.visibilityState 提供比 document.hidden 更直观的信息。它不仅告诉你页面是否隐藏,还能进一步区分页面是否正在预渲染。例如,你可以根据不同的状态采取不同的优化措施。

浏览器兼容性

虽然 Page Visibility API 很有用,但它的兼容性在不同浏览器中略有差异。以下是各主流浏览器的支持情况:

Document.hiddendocument.visibilityState
浏览器支持情况版本
Chrome支持自 33 版本起
Firefox支持自 18 版本起
Safari支持自 7 版本起
Edge支持自 12 版本起
Opera支持自 20 版本起
visibilitychange 事件
浏览器支持情况版本
Chrome支持自 62 版本起
Firefox支持自 56 版本起
Safari支持自 14.1 版本起
Edge支持自 18 版本起
Opera支持自 49 版本起

用户切换标签页时暂停视频播放

当用户切换标签页时,继续播放视频会浪费带宽和资源。通过 Page Visibility API,可以在页面不可见时暂停视频,等用户返回后再自动恢复播放。

const videoElement = document.querySelector("video");document.addEventListener("visibilitychange", function() {if (document.visibilityState === 'hidden') {// 页面隐藏时暂停视频videoElement.pause();console.log("页面隐藏,视频暂停");} else if (document.visibilityState === 'visible') {// 页面可见时恢复视频播放videoElement.play();console.log("页面可见,视频继续播放");}
});

页面不可见时停止资源密集型动画

动画可能是性能瓶颈,尤其是在页面不可见时运行动画毫无意义。通过 Page Visibility API,我们可以在页面不可见时暂停动画,减少 CPU 和 GPU 的消耗。

let animationRunning = true;function startAnimation() {if (!animationRunning) return;// 假设这里有动画逻辑console.log("动画正在运行...");requestAnimationFrame(startAnimation);
}document.addEventListener("visibilitychange", function() {if (document.visibilityState === 'hidden') {// 页面隐藏时停止动画animationRunning = false;console.log("页面隐藏,动画停止");} else if (document.visibilityState === 'visible') {// 页面可见时恢复动画animationRunning = true;startAnimation();console.log("页面可见,动画恢复");}
});startAnimation();

页面不可见时停止 API 请求

某些情况下,持续的数据获取可能会浪费带宽。通过检测页面的可见性,可以在页面不可见时停止数据请求,优化带宽使用。

let requestInterval;function startFetchingData() {requestInterval = setInterval(() => {// 模拟 API 请求console.log("正在获取数据...");}, 5000);
}function stopFetchingData() {clearInterval(requestInterval);console.log("停止获取数据");
}document.addEventListener("visibilitychange", function() {if (document.visibilityState === 'hidden') {// 页面隐藏时停止数据获取stopFetchingData();} else if (document.visibilityState === 'visible') {// 页面可见时恢复数据获取startFetchingData();}
});startFetchingData();

页面可见时恢复定时操作

当页面不可见时,某些定时任务可以暂停,直到用户返回页面时再恢复执行。这有助于提升资源利用效率。

let intervalId;function startTimer() {intervalId = setInterval(() => {console.log("计时器正在运行...");}, 1000);
}function stopTimer() {clearInterval(intervalId);console.log("计时器停止");
}document.addEventListener("visibilitychange", function() {if (document.visibilityState === 'hidden') {// 页面隐藏时停止计时器stopTimer();} else if (document.visibilityState === 'visible') {// 页面可见时恢复计时器startTimer();}
});startTimer();

用户返回页面时恢复音频播放

与视频类似,音频在页面不可见时继续播放不仅对用户无意义,还会浪费系统资源。通过 Page Visibility API 可以在用户返回页面时恢复音频播放。

const audioElement = document.querySelector("audio");document.addEventListener("visibilitychange", function() {if (document.visibilityState === 'hidden') {// 页面隐藏时暂停音频audioElement.pause();console.log("页面隐藏,音频暂停");} else if (document.visibilityState === 'visible') {// 页面可见时恢复音频播放audioElement.play();console.log("页面可见,音频继续播放");}
});

结论

Page Visibility API 是一个简单但非常有效的工具,能够让开发者根据页面的可见性来动态优化资源的使用。结合 document.visibilityState,你可以进一步细化页面状态的控制,如在页面预渲染时暂停某些操作。

这种优化不仅提升了用户体验,还能显著减少系统资源的浪费。通过合理利用这个 API,我们可以暂停后台的视频、音频、动画、数据请求等操作,并在用户重新关注页面时迅速恢复,达到性能和体验的双重提升。

在开发过程中,别忘了考虑浏览器的兼容性问题,确保在所有平台上提供一致的用户体验。希望这篇文章能够帮助你更好地掌握 Page Visibility API 并将其应用到实际项目中。

参考内容

  • 页面可见性 API - Web API | MDN (mozilla.org)
  • Document:visibilitychange 事件 - Web API | MDN (mozilla.org)
  • Document:hidden 属性 - Web API | MDN (mozilla.org)
  • Document.visibilityState - Web API | MDN (mozilla.org)

相关文章:

  • babylon.js-1:入门篇
  • 活体检测标签之2.4G有源RFID--SI24R2F+
  • 计算机毕业设计 基于Python的音乐平台的设计与实现 Python+Django+Vue 前后端分离 附源码 讲解 文档
  • SQL学习1
  • 通过fdisk初始化Linux数据盘
  • Xcode16适配
  • 机器学习(1):机器学习的概念
  • android 系统默认apn数据库
  • Vue 3 魔法揭秘:CSS 解析与 scoped 背后的奇幻之旅
  • 长沙某公司.Net高级开发面试题
  • 实战C++手写线程池
  • 【自用软件】IDM下载器 Internet Download Manager v6.42 Build 10
  • 黑马头条day5- 延迟任务精准发布文章
  • 前端框架对比与选择
  • Flink 性能优化的高频面试题及答案
  • Python_OOP
  • WordPress 获取当前文章下的所有附件/获取指定ID文章的附件(图片、文件、视频)...
  • 漫谈开发设计中的一些“原则”及“设计哲学”
  • 前端工程化(Gulp、Webpack)-webpack
  • Nginx惊现漏洞 百万网站面临“拖库”风险
  • ​configparser --- 配置文件解析器​
  • #pragam once 和 #ifndef 预编译头
  • #QT(智能家居界面-界面切换)
  • #中国IT界的第一本漂流日记 传递IT正能量# 【分享得“IT漂友”勋章】
  • (07)Hive——窗口函数详解
  • (13)Latex:基于ΤΕΧ的自动排版系统——写论文必备
  • (7) cmake 编译C++程序(二)
  • (C++)栈的链式存储结构(出栈、入栈、判空、遍历、销毁)(数据结构与算法)
  • (javaweb)Http协议
  • (k8s)Kubernetes 从0到1容器编排之旅
  • (WSI分类)WSI分类文献小综述 2024
  • (二)Optional
  • (翻译)Quartz官方教程——第一课:Quartz入门
  • (附源码)springboot 房产中介系统 毕业设计 312341
  • (七)理解angular中的module和injector,即依赖注入
  • (源码分析)springsecurity认证授权
  • (转)可以带来幸福的一本书
  • (最完美)小米手机6X的Usb调试模式在哪里打开的流程
  • .jks文件(JAVA KeyStore)
  • .NET : 在VS2008中计算代码度量值
  • .net core webapi 部署iis_一键部署VS插件:让.NET开发者更幸福
  • .NET 动态调用WebService + WSE + UsernameToken
  • .NET 中 GetProcess 相关方法的性能
  • .NetCore 如何动态路由
  • .NET周刊【7月第4期 2024-07-28】
  • @Builder用法
  • @Mapper作用
  • @SpringBootApplication 包含的三个注解及其含义
  • [ 数据结构 - C++] AVL树原理及实现
  • [2016.7.Test1] T1 三进制异或
  • [BZOJ 1032][JSOI2007]祖码Zuma(区间Dp)
  • [C#] 基于 Token 的鉴权与签名机制详解 接口对接鉴权 token、sign(a=1b=2c=3d=4)、Base64、参数加密、MD5
  • [c++] 什么是平凡类型,标准布局类型,POD类型,聚合体
  • [CareerCup] 12.3 Test Move Method in a Chess Game 测试象棋游戏中的移动方法
  • [Flex] PopUpButton系列 —— 控制弹出菜单的透明度、可用、可选择状态