Ios、Android微信瀏覽器後退跳轉實現,及遇到的bug

梧桐樹下的左右發表於2019-09-20

一、需求背景

  • 1、當前頁有一個彈窗,當使用者瀏覽器後退的時候不希望直接退出,而是將當前彈窗進行關閉,留在當前頁
  • 2、使用者進入當前頁點選瀏覽器後退的時候不希望使用者直接退出,使用瀏覽器後退跳轉到其它頁面,增加流量

二、功能實現

使用瀏覽器API window.history 進行後退控制,需要瀏覽器支援history(大部分移動瀏覽器都支援了) 程式碼示例:

// 新增瀏覽器歷史紀錄
history.pushState('test', '', '')
複製程式碼
// 監聽瀏覽器後退事件
window.onpopstate = function (e) {
  // 這裡進行業務邏輯的處理
  location.href = 'c.html'
}
複製程式碼

這樣在頁面載入的時候新增入新的瀏覽器紀錄就可以在後退的時候觸發 popState 事件,然後處理你的業務邏輯

三、遇到的BUG

  • 1、history.pushState在當前頁面重新整理一次頁面就會新增一次,當多次重新整理的時候會將history的長度加長,需要使用一個儲存變數進行判斷是否需要新增歷史紀錄,顯然H5新介面sessionStorage很適合當前使用,這樣在跳轉到後退頁面之後在使用瀏覽器後退會返回到當前頁,由於使用了判斷是當前頁不再進行歷史壓棧,就不會在重新觸發popState事件了,避免了無限次瀏覽器後退無限迴圈。
let active_view = sessionStorage.getItem('active_view')
if (!active_view) {
  sessionStorage.setItem('active_view', 'has')
}
複製程式碼
  • 2、Ios微信瀏覽器popstate的bug,在當前A.html頁跳轉到b.html頁,然後再b.html頁通過瀏覽器返回按鈕回到a.html頁面的時候會直接觸發popState事件,直接跳轉到c.html頁面了,真實需求是再b.html返回的時候回到a.html頁面,然後在a.html頁面的後退的時候才進行跳轉c.html頁面。所以我將Ios和Android區分開來,分別進行不同的業務處理。
// 判斷ios 的時候在第二次返回才進行頁面跳轉,不是的在重新將history增加
let jumps: any = sessionStorage.getItem('jump_number') || 0;
    let count = parseInt(jumps) + 1;
    let u = navigator.userAgent;
    let isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
    sessionStorage.setItem('jump_number', count);
    if (isIOS) {
      if (count >= 2) {
        // ios
        setJump();
      } else {
        pushHistory();
      }
    } else {
      // 其它
      setJump();
    }
複製程式碼

參考了 IOS微信瀏覽器返回事件popstate監聽

  • 3、頁面跳轉問題,在微信瀏覽器中直接使用location.href = c.html有可能頁面不會替換,其實顯示的還是a.html,需要點選重新整理頁面才是c.html,所以封裝了一個跳轉函式,加上一段列印log就可以正常跳轉了
// 需要將url列印出來頁面跳轉才會正常,(發稿之前還未弄清楚是什麼原因,以後知道了在附上)
function setJump(url) {
  // 跳轉
  console.log('連結:' + url);
  window.location.href = url;
}
複製程式碼
  • 4、當使用history.pushState(state, "test", "#")新增引數的時候,如果當前頁面的url中有#號,就是最後一個引數和url中最後的字元相同,會破壞popState事件,可能導致不觸發,因此使用引數加入歷史的需要注意投放連結的url,Android 手機部分機型在此情況下點選瀏覽器後退也會觸發兩次popState事件
// push 瀏覽器歷史記錄
function pushHistory() {
  let state = {
    title: "test",
    url: "#"
  };
  window.history.pushState(state, "test", "#")
}
複製程式碼

總結

  • 1、H5 頁面需要在很多平臺進行執行,有些是微信、支付寶內建瀏覽器的問題,也有很多是手機平臺的問題,需要相容許多機型和平臺的問題,比較複雜還有更多的平臺相容問題需要去處理。
  • 2、不同平臺對於window的API有一些差異,許多BUG都是該差異引起的,所以在遇到的時候多查查資料就可以了。

開發環境的問題

  • 1、大多數前端同學都是使用谷歌瀏覽器作為開發瀏覽器的。新版的谷歌瀏覽器點選後退按鈕不會觸發popState事件,需要在控制檯列印history.length在點選後退按鈕才會觸發(還不知道這個原因是什麼)

相關文章