最近在做手機版頁面,當離開時需要紀錄最後的狀態,一般來說最直覺會想到監聽 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)) 則不會。
因此在此情境中要準確抓到關閉視窗還是有點問題,現在暫時還沒有更好的解法,甚至有在考慮要不要在 document
或 window
上綁定 blur
事件 (XD)。但這個 API 仍然解決了部分的問題。
由於網站跨裝置的緣故,要處理的狀況也越來越多,另外還有 Page Lifecycle API 可以處理整個頁面生命週期的轉換,前端路真是越走越寬了~