監聽微信返回事件踩坑指南

PC瀏覽器返回等於從新進入上一個頁面,會觸發刷新動做,而微信不會。也就是困擾我多時的微信返回不刷新。chrome

大概再2017年初和2016末(大概也是從那個時候我開始作微信公衆號),還能夠經過在sessionStorage中記錄刷新標誌,讓上一個頁面根據標識刷新。也就是說當時微信返回仍是會觸發渲染事件的(具體是什麼事件也不清楚,由於當時沒有深究,可是確實是觸發了componentDidMount)。瀏覽器

可是某個時刻起,這種方法也再也不有效了,說明經過storage記錄須要刷新標誌是徹底失效的了。微信

另外能夠發現,上一個頁面會保持上一次操做的狀態,而且不會再有靜態資源的請求,不會觸發load事件。那也能夠這麼理解,在微信中的頁面跳轉,其實更相似於瀏覽器中的打開新標籤頁。因此上一個頁面的內容沒有被銷掉,而是會保持你跳走前的狀態。因此咱們不少頁面會有點擊返回可是loading仍是在轉的現象。session

嘗試一:visibilitychange

由此,我想到了第一個檢查他是否返回的方法——監聽頁面的visibilitychange事件。由於PC瀏覽器中若是標籤切換或者是瀏覽器縮略,其可見性改變的時候,都會觸發該事件。app

有興趣的能夠打開控制檯輸入如下代碼,看看有什麼不一樣。ide

window.addEventListener('visibilitychange', function () {
  console.log(document.hidden)
});

總之我先嚐試瞭如下代碼:fetch

let isPageBack = false; 

window.addEventListener('visibilitychange', function () {
  if(document.hiden){ 
     isPageBack = true
 } else if ( isPageBack ) {
     fetch('/data') //由於visibilitychange事件中alert能夠看到被模擬器禁了,因此就改用改了fetch本身的接口,經過查看日誌檢查是否觸發
 }
});

嘗試以後發現該事件並無被觸發。疑惑之餘,我嘗試了chrome手機瀏覽器,發現一樣,該事件沒有被觸發。url

另外,由於好奇若是app壓後臺會不會觸發該事件,因此嘗試這段代碼↓,結果發現即便壓後臺頁面也不會被掛起。日誌

setInterval(function () {
  var p = document.createElement('p');
  p.appendChild(document.createTextNode(`${Date.now()}`));
  document.body.appendChild(p);
}, 1000)

嘗試二:pageshow & pagehide

與visibilitychange相似的還有pageshowpagehide事件。code

pageshow事件觸發點是 a session history entry is being traversed to. 同時根據MDN的介紹在back/forward時也會被觸發

因而我改了改代碼

let isPageBack = false;

window.addEventListener('pageshow', function () {
  if (isPageBack ) fetch('/data')
})

window.addEventListener('pagehide', function () {
  isPageBack = true
})

竟然意外的能行,,,

pageshowpagehide事件能夠被監聽到。返回頁能夠經過頁面是否隱藏過知道是不是返回回來的。

嘗試三:history

history能夠修改歷史記錄或url主要是 history.pushStatehistory.replaceState

使用pushState 等於多推一條歷史記錄,replaceState 等於修改了歷史記錄,另外咱們要知道reload是不計入歷史記錄的。

理論上來講若是使用pushState修改url,那麼頁面訪問就會像這樣 A -> A1 -> B

當B返回A1時就會觸發 popstate 事件。在popstate事件裏面能夠作一些自定義的事情。

這裏用了代碼

var state = {
   date: Date.now()
 };
 window.history.pushState(state, 'csb');
 window.addEventListener('popstate', function (event) {
   if(event.state) location.reload()
 })

檢查history時,能夠看到state裏面有一個key是date的時間戳,同時歷史記錄的長度+1。
可是使用pushState會增長曆史記錄,會致使同一個頁面須要返回好幾回才能退出去,不過能夠利用他作返回退出公衆號

window.history.pushState({}, 'csb');
window.addEventListener('popstate', function (event) {
  if (event.state) { 
    wx.ready(function () {
      wx.closeWindow();
    });
  }
});

可是由於replaceState不會增長曆史記錄,因此利用它這樣返回刷新頁面

history.replaceState(null, null, '#');
window.addEventListener('popstate', function (event) {
 self.location.reload();
})

另外若是要若是A->B->C,而C返回時想要直接返回A能夠這樣

B頁面:

history.replaceState(null, null, '/c'); //將url替換成C,這樣跳轉到C頁面等於被轉變成了reload行爲,但直觀上來講,是咱們刪除了一條歷史記錄
相關文章
相關標籤/搜索