這是我參與8月更文挑戰的第6天,活動詳情查看:8月更文挑戰html
在Chrome
中,每個網頁標籤都是一個進程,當該標籤處於不可見狀態必定時間後會處於休眠狀態以節省內存等系統資源。咱們在開發時候有時須要檢測用戶是否處於當前頁面,以知足功能上的需求。html5
在以往,判斷用戶是否處於當前頁面,一般是判斷pagehide
、beforeunload
、unload
這三個事件,可是在移動端上不必定所有都會觸發,由於當前頁面被系統切換到另一個應用,以及系統殺死瀏覽器進程,是沒法監聽到的。當用戶切換應用,而後因爲內存不足或過久未使用,系統會直接殺死瀏覽器進程,此時unload
,beforeunload
會來不及觸發。webpack
Page Visibility API
,無論移動端仍是桌面,全部狀況下,都能監聽到頁面的可見性發生變化。使用它能夠加強用戶體驗,當用戶不在當前頁面時,能夠中止音視頻播放,網絡請求,動畫加載等,以節約資源和電量。web
Page Visibility API
的方法和屬性被掛載到document
對象上,咱們隨時都能調用它,它具備如下屬性:api
document.hidden
:窗口是否不可見,只讀屬性,當窗口處於徹底不可見時爲truedocument.visibilityState
:只讀屬性,表示當前窗口的狀態: 'hidden' | 'visible' | 'prerender'
,只要當前頁面有一丁點可見都爲true
。visibilitychange
:事件類型,當窗口的可見性發生變化時觸發。推薦使用document.visibilityState
而不是document.hidden
,它除了能檢測頁面的可見性還能檢測頁面是否處於預渲染階段。瀏覽器
只讀屬性,返回一個布爾值,表示頁面是否可見,爲true
時表示徹底不可見。緩存
相對於document.hidden
,document.visibilityState
能檢測更復雜的場景。它有三個狀態值:markdown
hidden
:頁面徹底不可見。visible
:頁面至少一部分可見。prerender
:頁面即將或正在渲染,處於不可見狀態。prerender
狀態只在支持"預渲染"的瀏覽器上纔會出現,好比 Chrome
就有預渲染功能,能夠在用戶不可見的狀態下,預先把頁面渲染出來,等到用戶要瀏覽的時候,直接展現渲染好的網頁。網絡
如下狀況爲hidden
:app
unload
)頁面。上面四種場景涵蓋了頁面可能被卸載的全部狀況。除了hidden
和prerender
,其餘時候只要有一點頁面顯示都爲visible
。
頁面卸載以前,document.visibilityState
必定會變成hidden
狀態,這也是W3C
設計這個API
的主要目的。
只要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
輪詢,中止頁面動畫特效等等,這些都能進一步提升頁面的性能和用戶體驗。
目前該接口獲得普遍的支持,web性能工做組織(Web Performance Working Group
)也提倡咱們在構建應用時使用該API
來提高提高應用性能和用戶體驗。