popstate事件在webkit中的詭異行爲

1、背景:同事去學校做畢設請假,今天幫他修改h5bug
2、遇到的問題:移動端App打開某個網頁會自動彈出一個對話框,這個對話框出現的不合時宜,因爲需要是在頁面做一些操作後點擊原生頂部的返回按鈕再彈出對話框
3、具體問題就是popstate造成的

4、原來的代碼:

window.addEventListener('popstate', function() {
var btnArray = ['我要退出', '繼續計數'];
mui.confirm('正在計數哦,確定要退出嗎?', '提示', btnArray, function(e) {
if(e.index == 1) {
pushHistory();
} else {
setBack();
}
})
},false);

5、修改後的代碼:

window.addEventListener('load', function() {
setTimeout(function() {
window.addEventListener('popstate', function() {
var btnArray = ['我要退出', '繼續計數'];
mui.confirm('正在計數哦,確定要退出嗎?', '提示', btnArray, function(e) {
if(e.index == 1) {
pushHistory();
} else {
setBack();
}
})
});
}, 0);
});

6、暫且先解決問題,日後有時間繼續深入研究

研究一陣

7、說說過去

以前瀏覽器操作瀏覽器歷史記錄主要依據history對象。在它的proto繼承有back、forward、go等函數,那麼什麼是popState?簡而言之就是HTML5新增的用來控制瀏覽器歷史記錄的api。

8、怎麼用?

HTML5的新API擴展了window.history,使歷史記錄點更加開放了。可以存儲當前歷史記錄點pushState、替換當前歷史記錄點replaceState、監聽歷史記錄點popstate。

history.pushState(data,title,url);
//其中第一個參數data是給state的值;第二個參數title爲頁面的標題,但當前所有瀏覽器都忽略這個參數,傳個空字符串就好;第三個參數url是你想要去的鏈接;

replaceState用法類似,例如:history.replaceState(“首頁”,”“,location.href+ “#web”);

兩者區別:pushState會改變history.length,而replaceState不改變history.length

9、有坑嗎?

popstate事件在webkit中的很詭異。popstate是HTML5的History系列中的事件,但是這玩意兒在webkit中的行爲相當讓人蛋疼。這回連IE10都站在了Firefox這邊,至少這邊的實用性強的多。雖然官方的文檔中對popstate的描述也沒有細節上的描述,不過以我的邏輯來判斷,這貨是就webkit的BUG。

Html5這套ApI和傳統的history不同,或者說這套API是“session history entries”。

注意注意:Html5種的HistoryAPI是不會使頁面跳轉的,只是操作地址欄和相應的state屬性而已,而且它是手動操作的。瀏覽器默認的History還是傳統的那一套,雖然它們在瀏覽器上都使用同一個“歷史記錄堆棧”。

對這個差異的認知就是webkit中詭異行爲的原因。webkit並沒有把HTML5的History和傳統的區分開,而根據官方文檔對popstate的描述,只要訪問歷史記錄就會觸發popstate。而傳統的History中訪問頁面和生產歷史記錄是同時的。所以在webkit中,無論是刷新還是訪問一個新網頁都會觸發popstate。而其它瀏覽器中這個popstate僅作用於HTML5的History,並不響應傳統的History,更不用說刷新和訪問新網頁的情況了。

原因找到了,那麼解決方案呢?

1、對popstate延遲綁定的方法,因爲popstate會在頁面加載完成之後不久觸發,所以在setTimeout一段時間後再綁定事件,popstate的第一次就不會輕易被webkit奪走了
2、判斷瀏覽器再做調整,直接針對webkit在頁面加載完成後第一次觸發的popstate屏蔽了

發佈了42 篇原創文章 · 獲贊 6 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章