Page Visibility API
頁面可見性 API 提供了可供監視的事件,以便了解文件何時變為可見或隱藏,以及用於檢視頁面當前可見狀態的功能。
這對於節省資源和提高效能特別有用,因為它允許頁面在文件不可見時避免執行不必要的任務。
概念與用法
當用戶最小化視窗、切換到另一個標籤頁,或者文件被另一個視窗完全遮擋時,API 會發送一個 visibilitychange 事件,讓監聽器知道頁面的狀態已更改。您可以檢測到該事件並執行一些操作或表現出不同的行為。例如,如果您的 Web 應用正在播放影片,它可以在使用者將標籤頁移到後臺時暫停影片,並在使用者返回標籤頁時恢復播放。使用者不會丟失影片的進度,影片的音軌不會干擾新前臺標籤頁中的音訊,並且使用者在此期間不會錯過任何影片內容。
<iframe> 的可見性狀態與父文件相同。使用 CSS 屬性(如 display: none;)隱藏 <iframe> 不會觸發可見性事件,也不會改變框架內文件的狀態。
用例
讓我們考慮頁面可見性 API 的幾個用例。
- 一個網站有一個圖片輪播,除非使用者正在檢視頁面,否則不應前進到下一張幻燈片
- 一個顯示資訊儀表板的應用程式不希望在頁面不可見時輪詢伺服器以獲取更新
- 一個網站希望在裝置進入待機模式時關閉聲音(使用者按下電源按鈕關閉螢幕)
開發人員過去曾使用不完美的代理來檢測這一點。例如,監視視窗的 blur 和 focus 事件有助於瞭解何時您的頁面不是活動頁面,但它不能告訴您您的頁面實際上對使用者是隱藏的。頁面可見性 API 解決了這個問題。
為提高後臺頁面效能而制定的策略
與頁面可見性 API 分開,使用者代理通常有許多策略來減輕後臺或隱藏標籤頁的效能影響。這些可能包括
- 大多數瀏覽器會停止向後臺標籤頁或隱藏的
<iframe>傳送requestAnimationFrame()回撥,以提高效能和電池壽命。 setTimeout()等計時器在後臺/不活動標籤頁中受到限制,以幫助提高效能。有關更多詳細資訊,請參閱 setTimeout() 的延遲原因。- 瀏覽器實現了基於預算的後臺超時限制。這在現代瀏覽器中的執行方式類似,具體細節如下:
- 在 Firefox 中,後臺標籤頁中的視窗各有自己的時間預算(以毫秒為單位),最大值為 +50 ms,最小值為 -150 ms。Chrome 非常相似,只是預算以秒為單位指定。
- 視窗將在 30 秒後受到限制,與視窗計時器指定的限制延遲規則相同(同樣,請參閱 setTimeout() 的延遲原因)。在 Chrome 中,此值為 10 秒。
- 只有當預算為非負數時,才允許計時器任務。
- 一旦計時器的程式碼執行完畢,它所花費的執行時間將從其視窗的超時預算中扣除。
- 在 Firefox 和 Chrome 中,預算以每秒 10 ms 的速率再生。
有些程序不受此限制行為的影響。在這些情況下,您可以使用頁面可見性 API 來減少隱藏選項卡在隱藏時的效能影響。
- 正在播放音訊的選項卡被視為前臺,不會受到限制。
- 正在執行使用即時網路連線(WebSockets 和 WebRTC)的程式碼的選項卡不會受到限制,以避免關閉這些連線導致超時並意外關閉。
- IndexedDB 程序也不會受到限制,以避免超時。
其他介面的擴充套件
例項屬性
頁面可見性 API 向 Document 介面添加了以下屬性:
-
如果頁面處於對使用者隱藏的狀態,則返回
true,否則返回false。 Document.visibilityState只讀-
一個指示文件當前可見狀態的字串。可能的值為:
visible-
頁面內容至少部分可見。實際上,這意味著頁面是未最小化視窗的前臺標籤頁。
-
頁面的內容對使用者不可見,原因可能是文件的標籤頁處於後臺,或者是一個已最小化的視窗的一部分,或者是因為裝置的螢幕已關閉。
事件
頁面可見性 API 向 Document 介面添加了以下事件:
visibilitychange-
當標籤頁的內容變得可見或被隱藏時觸發。
示例
頁面隱藏時暫停音訊
此示例會在頁面隱藏時暫停正在播放的音訊,並在頁面再次可見時恢復播放。<audio> 元素控制元件允許使用者在播放和暫停音訊之間切換。布林值 playingOnHide 用於防止在頁面切換到 visible 狀態但媒體在頁面隱藏時未播放的情況下播放音訊。
HTML
<audio
controls
src="https://mdn.github.io/webaudio-examples/audio-basics/outfoxing.mp3"></audio>
JavaScript
const audio = document.querySelector("audio");
let playingOnHide = false;
document.addEventListener("visibilitychange", () => {
if (document.hidden) {
playingOnHide = !audio.paused;
audio.pause();
} else if (playingOnHide) {
// Page became visible! Resume playing if audio was "playing on hide"
audio.play();
}
});
結果
規範
| 規範 |
|---|
| HTML # dom-document-visibilitystate |
瀏覽器相容性
載入中…