最近在項目中遇到一個webview中的返回問題,以爲比較有價值,在這裏記錄下。javascript
需求是在安卓客戶端APP中用webview
打開vue
的單頁應用,在vue
應用中,路由本身管理,每次點擊導航欄的返回按鈕,都返回上級路由頁面,當回到最初webview
打開所在的頁面時,再點擊返回按鈕,就調用客戶端提供的 clientApi.goBack()
方法,會銷燬掉這個webview
,回到客戶端app所在的頁面。vue
在這個 vue
應用中,有 A、B、C、D、E,五個頁面,彼此之間均可以相互跳轉,每一個頁面均可能是客戶端APP打開webview
時所處的第一個頁面。那麼問題來了,假設某一次打開 webview
時,進入的是 C
頁面,在應用內各類跳轉,而後一級級地返回,返回到了 C
頁面,如何判斷該調用 clientApi.goBack()
了呢?java
我嘗試在 C
頁面調用 router.back()
, 沒有任何反應,固然,這是JS
的代碼,銷燬webview
已經超出了它的權限。在 route
和 router
中都沒有找到任何能判斷當前頁面就是打開 webview
時所在的頁面的線索,又嘗試在 window.history
中找找線索。web
window.history
有三個屬性:app
length
scrollRestoration
state
前面兩個用不了,因而嘗試下state
.ui
發現每次路由變化以後,window.history.state
都是不一樣的值, 例如:this
{
key: "icgo4i",
state: undefined
}
複製代碼
初始頁面的 window.history.state
多是 null
, 也多是一個如上的對象。嘗試進行幾回路由跳轉,而後再返回,發現同一個頁面,在不一樣的路由時機,其 window.history.state
的值是不一樣的,好比,當前在 A
頁面,其 window.history.state
值爲:spa
{
key: "icgo4i",
state: undefined
}
複製代碼
跳轉到 B
頁面,由B
頁面跳轉至 C
頁面,再由 C
頁面跳轉至 A
頁面,那麼此時 A
頁面的 window.history.state
的值爲:code
{
key: "0yfpsb",
state: undefined
}
複製代碼
與前一個 A
頁面的值是不一樣的。router
而後再由A
頁面一路調用 router.back()
或者window.history.back()
,返回到最初的 A
頁面,此時 window.history.state
值又變成了:
{
key: "icgo4i",
state: undefined
}
複製代碼
能夠看到,與原來的值同樣。
問題終於有了解決方案,根據 window.history.state
的記憶功能,即可以判斷當前頁面是不是打開 webview
時所處的頁面。步驟以下:
window.history.state
window.history.state
與所記錄的值是否同樣clientApi.goBack()
, 不然調用 router.back()
vue
版參考代碼以下:// store
state: {
initialHistoryStateStr: '',
}
mutations: {
setHistoryInitialStateStr(state: State, initialHistoryStateStr: string) {
state.initialHistoryStateStr = initialHistoryStateStr;
},
}
// common.js
if (store.state.initialHistoryStateStr === JSON.stringify(window.history.state)) {
clientApi.goBack();
} else {
router.back();
}
// App
created() {
this.$store.commit('setHistoryInitialStateStr', JSON.stringify(window.history.state));
window.handleClientGoBack = () => {
common.goBack();
};
clientApi.on('back', handleClientGoBack'); // 監聽客戶端物理返回按鍵點擊
}
複製代碼
js
版參考代碼以下:window.addEventListener('load', function() {
window.__initialHistoryStateStr = JSON.stringify(window.history.state);
}, false);
const common = {
back() {
const nowHistoryStateStr = JSON.stringify(window.history.state);
if (nowHistoryStateStr === window.__initialHistoryStateStr) {
clientApi.goBack();
} else {
window.history.back();
}
}
}
window.handleClientGoBack = () => {
common.goBack();
};
clientApi.on('goBack', 'handleClientGoBack'); // 監聽客戶端物理返回按鍵點擊
複製代碼