JS監聽手機物理返回鍵(及IOS微信端的bug)

來發暴擊_leywis發表於2018-12-11

需求場景

有一天,頭兒給我提了這樣一個需求:

無論頁面如何跳轉,在首頁的時候再按返回,直接退出...

解決思路

關閉網頁好說,由於我們的專案是微信公眾號,直接呼叫微信瀏覽器的內建函式:

WeixinJSBridge.call('closeWindow')
複製程式碼

但是怎麼監聽到這個返回的事件呢?辦法呢還是有滴!

1. popstate-一個可以監聽歷史記錄點的API

JavaScript中沒有監聽物理返回鍵的API,所以通過監聽瀏覽器歷史記錄的變化來實現。

在HTML5就提供給我們 popstate 用來監聽歷史記錄點。

window.addEventListener("popstate", function(e) { 
    // 如果監聽到返回,就跳轉到百度首頁
    window.location = 'http://www.baidu.com';
}, false); 
複製程式碼

2. 監聽不到?pushState來告訴你為什麼

當我們完成兩個頁面來測試步驟一中程式碼的時候,發現返回的時候根本沒跳轉到百度首頁。

hi

轉念一想不對啊,監聽到popstate事件的一瞬間就返灰到上一頁面了啊。為啥沒反應,心裡有點了逼數了啊!

不賣關子了,為了能返回後不回到上一級頁面,可以使用 pushState 來向歷史記錄棧中在插入一條新紀錄。

注意: 此處為了返回不跳轉,插入一個錨連結(此處有坑,下文解釋)就行


/**
* window.history.pushState(state, title, url)
*
* state:與要跳轉到的URL對應的狀態資訊。
* title:現在大多數瀏覽器不支援或者忽略這個引數,最好用null代替。
* url:要跳轉到的URL地址,不能跨域。
**/ 

var state = { 
    title: "title", 
    url: "#"
}; 
window.history.pushState(state, null, "#"); 

複製程式碼

沒意外的話,現在配合步驟一中程式碼,是可以監聽到頁面返回事件,從而跳轉到百度首頁。這也是網上能看到的絕大多數的思路。提醒一下,replaceState 雖然也可以改變歷史記錄棧,但是為了不破壞原有歷史記錄,此處最好使用 pushState

3. 簡單整理一下前兩步中程式碼

// 封裝一下push歷史記錄的方法
function pushHistory() { 
    var state = { 
        title: "title", 
        url: "#" 
    }; 
    window.history.pushState(state, null, "#"); 
} 

// 在需要監聽的頁面執行該方法
pushHistory();
window.addEventListener("popstate", function(e) { 
    // 如果監聽到返回,就跳轉到百度首頁
    window.location = 'http://www.baidu.com';
}, false); 
複製程式碼

問題蒐集(網上搜集)

在微信中進入頁面就觸發了popstate事件

解決方法:定義boolean 變數bool=false。在頁面載入後,採用setTimeout方法設定1.5s的超時,在超時執行方法中設定bool=true。

// 封裝一下push歷史記錄的方法
function pushHistory() { 
    var state = { 
        title: "title", 
        url: "#" 
    }; 
    window.history.pushState(state, null, "#"); 
} 

// 在需要監聽的頁面執行該方法
var bool=false;
setTimeout(function(){
   bool=true;
},1500);

pushHistory();
window.addEventListener("popstate", function(e) { 
    // 如果監聽到返回,就跳轉到百度首頁
    if(bool){
        window.location = 'http://www.baidu.com';   
    }
    pushHistory();
}, false); 
複製程式碼

這是網上看到好多人遇到的問題,雖然加了延遲,但是仍然解決不了我的問題,也許是應用場景的不同,此處暫時記下,做個參考

IOS微信端popstate自動觸發的解決

在IOS端的微信,如果頁面A->頁面B,如果兩個頁面都設定了返回重定向(也就是以上程式碼),按下返回鍵的時候,頁面A的popstate也會自動觸發,管你設定多少延遲也沒用。

當時在網上找了很多方法,都沒解決。

也許是自己手欠的緣故,有一次在毫無思路的情況下,在錨連結後加了個標識:

// 封裝一下push歷史記錄的方法
function pushHistory() { 
    var state = { 
        title: "title", 
        url: "#forward" 
    }; 
    window.history.pushState(state, null, "#forward"); 
} 

// 在需要監聽的頁面執行該方法
pushHistory();
window.addEventListener("popstate", function(e) { 
    // 如果監聽到返回,就跳轉到百度首頁
    window.location = 'http://www.baidu.com';
}, false); 
複製程式碼

你妹的,居然解決了

當然,此時我原來加的延遲也去掉了,反正對我來說也沒什麼用了!

總結: 在使用以上方式實現返回重定向的時候,切記不要只push進去一個空錨點。希望我這次的經驗能給遇到同樣問題的朋友一些經驗。如果有朋友有更好的解決辦法,也希望可以分享給我!

相關文章