[JS] Page Visibility API


最近在做手機版頁面,當離開時需要紀錄最後的狀態,一般來說最直覺會想到監聽 beforeunload 和 unload 兩個事件,然而測試發現這兩個事件在關閉頁籤和回到桌面時不會觸發,反而是重新整理才會觸發。
Testing on:
Chrome 71.0.3578 @ iPhone XS (iOS 12.0.1)
Safari 12.0 @ iPhone XS (iOS 12.0.1)
Chrome 71.0.3578 @ Sony XZ (Android 8.0.0)

而且在手機上,使用者也可能直接回到桌面後透過應用程式管理員關閉瀏覽器,如此一來就無法準確紀錄到使用者的行為。為了解決這個問題,W3C 提出了 Page Visibility API,透過此 API,可以監聽到頁面的可見性變化。

visibilityState 屬性

API 在 document 增加了 document.visibilityState 屬性,回傳三個值來表示頁面可見的狀態:

  • hidden:頁面不可見
  • visible:頁面至少部分可見
  • prerender:頁面即將或正在渲染,處於不可見狀態(如 chrome 瀏覽器在不可見狀態下,會先將頁面預先渲染出來,等用戶瀏覽的時候再直接展示。)

在以下情況頁面會是 hidden

  • 瀏覽器最小化
  • 瀏覽器被切換到背景
  • 瀏覽器將要卸載 (unload)
  • 操作系統觸發螢幕鎖定

如此一來,我們就能夠在頁面不可見的情況下停掉一些行為,像是影片、音檔播放、API 輪詢、Slider 計時等等。

基於歷史原因,API 還包含了 document.hidden 屬性,返回布林值。在可以的情況下,都建議使用 document.visibilityState 屬性。

visibilitychange 事件

document.visibilityState 屬性發生變化,就會觸發 visibilitychange 事件,因此可以監聽此事件來追蹤頁面可見性的變化。

實務

經過實機測試,在以下情況下可以正確觸發事件,並且 document.visibilityState 屬性為 hidden

  • 切換應用程式
  • 回到桌面

而「關閉視窗」則有點微妙,在 Chorme 71.0.3578 @ iPhone XS (iOS 12.0.1) 會觸發,其餘兩個情況 (Safari 604.1 @ iPhone XS (iOS 12.0.1)、Chorme 71.0.3578 @ Sony XZ (Android 8.0.0)) 則不會。

因此在此情境中要準確抓到關閉視窗還是有點問題,現在暫時還沒有更好的解法,甚至有在考慮要不要在 documentwindow 上綁定 blur 事件 (XD)。但這個 API 仍然解決了部分的問題。

由於網站跨裝置的緣故,要處理的狀況也越來越多,另外還有 Page Lifecycle API 可以處理整個頁面生命週期的轉換,前端路真是越走越寬了~

參考資料


發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *