Visibility API是用来检查网页是不是被用户看到了,这样你就能知道用户是怎么跟你网页互动的,还能给一些关于应用状态的提示。Visibility API还能设置监听器,在页面可见性变化时执行回调。那如何用这个API,还有得避开哪些常见的坑呢?
什么是Visibility API?
最初,Visibility API是作为独立规范开发的,但它被直接纳入页面可见性下的HTML规范中。此API公开了一种确定文档可见性状态的方法,以便您可以检查网页是“可见”还是“隐藏”。这听起来很简单,但页面可以通过几种不同的方式“隐藏”。
如果带有该页面的浏览器窗口被最小化,如果它被另一个应用程序完全遮挡,或者用户切换到另一个选项卡,则页面是“隐藏的”。如果操作系统的屏幕锁被激活,页面可见性也会变为“隐藏”,因此移动设备的行为也会被考虑在内。相比之下,即使页面在屏幕上部分可见,它仍然“可见”。
如何感知页面的可见/隐藏
您可以使用document.visibilityState检查文档的可见性,它将返回可见或隐藏。或者,您可以检查document.hidden Boolean属性的值:
console.log(document.visibilityState); // "visible"
console.log(document.hidden); // false
document.hidden不推荐使用,只是由于历史原因而保留,不过目前也没有具体文档可以看到需要取消。
在实践中,使用visibilitychange event也很方便,您可以在页面的可见性状态发生变化时触发业务逻辑,而不是手动检查可见性:
document.addEventListener("visibilitychange", (event) => {
// doSomething();
});
当状态发生变化时,您可以检查页面可见性,然后根据结果做一些事情:
document.addEventListener("visibilitychange", () => {
if (document.visibilityState === "visible") {
// The page is visible again!
}
});
为什么页面可见性很有用
页面可见性在许多情况下是有用的,其中最合适的业务场景是埋点分析、资源管理优化,以及改善用户体验(UX)的功能。让我们更详细地看看这些。
埋点分析
在分析领域中,当页面从可见变为隐藏时,通常会记录该点。页面更改为隐藏状态可能是页面可以观察到的最后一个事件,因此开发人员通常将其视为用户会话的结束。然而,这在很大程度上取决于你如何定义“会话”。您可以根据固定的不活动时间定义会话,而不是完全依赖“第一页隐藏”。因此,此用例将根据您的需求而有所不同:
document.addEventListener("visibilitychange", () => {
if (document.visibilityState === "hidden") {
navigator.sendBeacon("/log", analyticsData);
}
};
资源管理
当访问者不再查看页面时,我们可以通过Visibility API做一些优化。例如
-
暂停和恢复定时任务:当页面处于不可见状态时,可以暂停不必要的定时任务,以减少CPU和内存的使用。
-
暂停和恢复动画:当页面不可见时,暂停动画以节省资源,当页面重新可见时恢复动画。
-
暂停和恢复媒体播放:当页面不可见时,可以暂停音视频播放,当页面重新可见时恢复播放。
-
延迟或暂停数据轮询:对于需要定期从服务器获取数据的应用,可以在页面不可见时暂停轮询,当页面重新可见时恢复轮询。
-
降低内存使用:当页面长时间不可见时,可以释放某些占用大量内存的资源,例如缓存的图片或不再需要的数据。
-
减少网络请求:当页面不可见时,可以减少或暂停某些不必要的网络请求,以降低带宽使用和服务器负载。
改善用户体验
当页面从隐藏变为可见时,我们可以假设访问者已返回我们的页面,因此我们可以重新启动页面隐藏时可能暂停的任何内容。
在MDN的Visibility API介绍时,有这样一个很好的例子。
<audio controls src="xxxx.mp3"></audio>
const audio = document.querySelector("audio");
document.addEventListener("visibilitychange", () => {
if (document.hidden) {
audio.pause();
} else {
audio.play();
}
});
在HTML中,有一个元素,控件可见,因此用户可以启动和停止媒体。在JavaScript中,我们正在查看可见性更改事件,并执行以下操作:
-
如果页面被隐藏,请暂停音频。
-
如果显示页面,请播放音频。
到这里,我们就能很好的控制音频的播放与否了,但在实际应用中,我们应该做多一步,检测是否有播放过,如果一开始用户都没播放过,我们就自动播放了,那反倒造成了干扰,所以最好用一个变量记录播放状态。:
const audio = document.querySelector("audio");
let playingOnHide = false;
document.addEventListener("visibilitychange", () => {
if (document.hidden) {
playingOnHide = !audio.paused;
audio.pause();
} else {
if (playingOnHide) {
audio.play();
}
}
});
浏览器兼容性总结
Visibility API 的兼容性在现代浏览器中相当好,但仍有一些需要注意的地方,特别是针对旧版本的浏览器。以下是关于Visibility API 兼容性的详细说明:
以下是支持Visibility API 的浏览器版本:
-
Google Chrome: 从版本 13 开始支持。
-
Mozilla Firefox: 从版本 10 开始支持。
-
Microsoft Edge: 从版本 12 开始支持。
-
Internet Explorer: 从版本 10 开始支持。
-
Safari: 从版本 7 开始支持。
-
Opera: 从版本 12.10 开始支持。
在某些早期版本的浏览器中,Visibility API 需要使用浏览器厂商的前缀。以下是这些前缀及其对应的事件和属性:
-
Chrome: 使用
webkit前缀。 -
Firefox: 使用
moz前缀。 -
Internet Explorer: 使用
ms前缀。
为了兼容所有可能的情况,你可以编写以下代码来检测页面可见性:
var hidden, visibilityChange;
if (typeof document.hidden !== "undefined") {
hidden = "hidden";
visibilityChange = "visibilitychange";
} else if (typeof document.mozHidden !== "undefined") {
hidden = "mozHidden";
visibilityChange = "mozvisibilitychange";
} else if (typeof document.msHidden !== "undefined") {
hidden = "msHidden";
visibilityChange = "msvisibilitychange";
} else if (typeof document.webkitHidden !== "undefined") {
hidden = "webkitHidden";
visibilityChange = "webkitvisibilitychange";
}
function handleVisibilityChange() {
if (document[hidden]) {
console.log("页面不可见");
} else {
console.log("页面可见");
}
}
if (typeof document.addEventListener === "undefined" || hidden === undefined) {
console.log("Page Visibility API 不受支持");
} else {
document.addEventListener(visibilityChange, handleVisibilityChange, false);
}
检查 API 支持情况
在实现页面可见性功能之前,最好先检查浏览器是否支持Visibility API:
if (typeof document.hidden !== "undefined" ||
typeof document.mozHidden !== "undefined" ||
typeof document.msHidden !== "undefined" ||
typeof document.webkitHidden !== "undefined") {
// 浏览器支持 Page Visibility API
} else {
// 浏览器不支持 Page Visibility API
}
Page Visibility API 在大多数现代浏览器中都得到了广泛支持,但在处理旧版本的浏览器时,需要考虑使用厂商前缀。此外,确保在代码中正确地检查 API 的可用性,并在必要时提供回退方案,可以使你的网页在更多的浏览器中正常工作。
相似API
与visibilitychange相似的api有onpageshow,这两者有什么差异呢?
window.onpageshow 和 visibilitychange 事件都与页面的生命周期有关,它们各自有不同的用途和触发条件:
-
window.onpageshow事件:-
这个事件在页面被展示给用户时触发,无论页面是首次加载、从会话历史中加载,还是从缓存加载。
-
它提供了一个事件对象,其中包含一个
persisted属性,该属性指示页面是否是从缓存中恢复的。 -
onpageshow事件可以在页面的window对象上设置,例如:window.onpageshow = function(event) { // 页面展示时执行的代码 if (event.persisted) { // 页面是从缓存中恢复的 } };
-
-
visibilitychange事件:-
这个事件由 Visibility API 提供,当页面的可见性状态发生变化时触发,例如用户切换标签页或最小化浏览器窗口。
-
事件触发时,可以通过
document.hidden属性或document.visibilityState来检测页面当前是否可见。 -
visibilitychange事件也可以在document对象上设置监听器,例如:document.addEventListener('visibilitychange', function() { if (document.hidden) { // 页面不可见 } else { // 页面可见 } });
-
它们之间的关系和区别:
- 触发条件不同:
onpageshow在页面展示时触发,而visibilitychange在页面的可见性状态变化时触发。 - 用途不同:
onpageshow适合执行页面展示时的初始化操作,如检查页面是否从缓存恢复,并据此调整行为。visibilitychange适合执行与页面可见性相关的操作,如暂停或恢复视频播放、暂停轮询等。 - 页面加载和历史记录导航:
onpageshow可以在页面加载和历史记录导航时提供有用的信息,而visibilitychange专注于页面的可见性状态,与页面加载过程无关。 - 用户体验:
visibilitychange可以用于优化用户体验,比如在页面不可见时减少资源消耗,而onpageshow可以用于恢复用户离开时的状态。
总结
在本文中,我们深入探讨了页面可见性(Page Visibility API)的概念、实现方法以及它在现代网页开发中的应用。通过使用Visibility API,开发者能够更智能地管理资源、优化用户体验,并进行有效的用户行为分析。