HTML5起航____微信內(nèi)置瀏覽器的一波返回操作


引言

最近心氣比較浮躁发皿,潛意識(shí)告訴自己慢一點(diǎn)蛙卤,再慢一點(diǎn),感覺只是說給自己聽的宰翅。

為了緩和一下自己扭曲的心態(tài)弃甥,寫篇博文治療治療~


利用popstate事件和window下的history對象處理瀏覽器跳轉(zhuǎn)

1、popstate事件

參考文檔地址

當(dāng)活動(dòng)歷史記錄條目更改時(shí)汁讼,將觸發(fā)popstate事件淆攻。如果被激活的歷史記錄條目是通過對history.pushState()的調(diào)用創(chuàng)建的,或者受到對history.replaceState()的調(diào)用的影響嘿架,popstate事件的state屬性包含歷史條目的狀態(tài)對象的副本瓶珊。

需要注意的是調(diào)用history.pushState()或history.replaceState()不會(huì)觸發(fā)popstate事件。只有在做出瀏覽器動(dòng)作時(shí)耸彪,才會(huì)觸發(fā)該事件伞芹,如用戶點(diǎn)擊瀏覽器的回退按鈕(或者在Javascript代碼中調(diào)用history.back())

不同的瀏覽器在加載頁面時(shí)處理popstate事件的形式存在差異。頁面加載時(shí)Chrome和Safari通常會(huì)觸發(fā)(emit )popstate事件蝉娜,但Firefox則不會(huì)唱较。

2、History 接口

屬性:

  • History.length 表示歷史會(huì)話中元素的數(shù)目
  • History.scrollRestoration 允許Web應(yīng)用程序在歷史導(dǎo)航上顯式地設(shè)置默認(rèn)滾動(dòng)恢復(fù)行為召川。此屬性可以是自動(dòng)的(auto)或者手動(dòng)的(manual)南缓。
  • History.state 返回一個(gè)表示歷史堆棧頂部的狀態(tài)的值。這是一種可以不必等待popstate 事件而查看狀態(tài)的方式荧呐。

方法:

  • History.back()

等同于history.go(-1)

  • History.forward()

等同于history.go(1)

  • History.go()

這個(gè)方法中如果參數(shù)超出范圍或者不對就不會(huì)起效果

  • History.pushState()

pushState() 帶有三個(gè)參數(shù):一個(gè)狀態(tài)對象汉形,一個(gè)標(biāo)題(現(xiàn)在被忽略了)纸镊,以及一個(gè)可選的URL地址。下面將對這三個(gè)參數(shù)進(jìn)行細(xì)致的檢查

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

監(jiān)聽瀏覽器返回按鈕

function pushHistory() {  
  var state = {  
    title: "title",  
    url: "#"  
  };  
  window.history.pushState(state, "title", "#xx");  
}
pushHistory();
window.addEventListener("popstate", function(e) {  
console.log(e);
alert("我監(jiān)聽到了瀏覽器的返回按鈕事件啦");//根據(jù)自己的需求實(shí)現(xiàn)自己的功能  
}, false);

這個(gè)地方就監(jiān)聽到了瀏覽器的返回事件概疆,但我有個(gè)疑問逗威,如果不先pushState一個(gè)地址就監(jiān)聽不到,直接跳轉(zhuǎn)了岔冀,這個(gè)暫時(shí)沒搞懂庵楷。

禁止返回上一頁的一種方案

history.pushState(null, null, document.URL);
window.addEventListener("popstate",function(e) {  
  console.log(e);
  history.pushState(null, null, document.URL);
}, false);

這個(gè)其實(shí)就是利用pushState向?yàn)g覽歷史列表中插入當(dāng)前頁面,在點(diǎn)擊后退和前進(jìn)時(shí)都插入一次楣颠,那樣無論點(diǎn)前進(jìn)還是后退永遠(yuǎn)都會(huì)留在這個(gè)頁面了

其他方法就不一一列舉了尽纽,感興趣的看文檔



  • History.back()

前往上一頁, 用戶可點(diǎn)擊瀏覽器左上角的返回按鈕模擬此方法. 等價(jià)于 history.go(-1).

Note: 當(dāng)瀏覽器會(huì)話歷史記錄處于第一頁時(shí)調(diào)用此方法沒有效果,而且也不會(huì)報(bào)錯(cuò)童漩。

  • History.forward()

在瀏覽器歷史記錄里前往下一頁弄贿,用戶可點(diǎn)擊瀏覽器左上角的前進(jìn)按鈕模擬此方法. 等價(jià)于 history.go(1).

  • History.go()

通過當(dāng)前頁面的相對位置從瀏覽器歷史記錄( 會(huì)話記錄 )加載頁面。比如:參數(shù)為-1的時(shí)候?yàn)樯弦豁摻门颍瑓?shù)為1的時(shí)候?yàn)橄乱豁? 當(dāng)整數(shù)參數(shù)超出界限時(shí)( 譯者注:原文為When integerDelta is out of bounds )差凹,例如: 如果當(dāng)前頁為第一頁,前面已經(jīng)沒有頁面了侧馅,我傳參的值為-1危尿,那么這個(gè)方法沒有任何效果也不會(huì)報(bào)錯(cuò)。調(diào)用沒有參數(shù)的 go() 方法或者不是整數(shù)的參數(shù)時(shí)也沒有效果馁痴。( 這點(diǎn)與支持字符串作為url參數(shù)的IE有點(diǎn)不同)谊娇。

  • History.pushState()

按指定的名稱和URL(如果提供該參數(shù))將數(shù)據(jù)push進(jìn)會(huì)話歷史棧,數(shù)據(jù)被DOM進(jìn)行不透明處理罗晕;你可以指定任何可以被序列化的javascript對象济欢。

在HTML 文件中, history.pushState() 方法向?yàn)g覽器歷史添加了一個(gè)狀態(tài)。

pushState() 帶有三個(gè)參數(shù):一個(gè)狀態(tài)對象小渊,一個(gè)標(biāo)題(現(xiàn)在被忽略了)法褥,以及一個(gè)可選的URL地址。下面將對這三個(gè)參數(shù)進(jìn)行細(xì)致的檢查:

state object — 狀態(tài)對象是一個(gè)由 pushState()方法創(chuàng)建的酬屉、與歷史紀(jì)錄相關(guān)的JS對象半等。當(dāng)用戶定向到一個(gè)新的狀態(tài)時(shí),會(huì)觸發(fā)popstate事件呐萨。事件的state屬性包含了歷史紀(jì)錄的state對象杀饵。(譯者注:總而言之,它存儲(chǔ)JSON字符串垛吗,可以用在popstate事件中凹髓。)state 對象可以是任何可以序列化的東西。由于 火狐 會(huì)將這些對象存儲(chǔ)在用戶的磁盤上怯屉,所以用戶在重啟瀏覽器之后這些state對象會(huì)恢復(fù)蔚舀,我們施加一個(gè)最大640k 的字符串在state對象的序列化表示上。如果你像pushState() 方法傳遞了一個(gè)序列化表示大于640k 的state對象锨络,這個(gè)方法將扔出一個(gè)異常赌躺。如果你需要更多的空間,推薦使用sessionStorage或者localStorage羡儿。

title — 火狐瀏覽器現(xiàn)在已經(jīng)忽略此參數(shù)礼患,將來也許可能被使用÷庸椋考慮到將來有可能的改變缅叠,傳遞一個(gè)空字符串是安全的做法。當(dāng)然虏冻,你可以傳遞一個(gè)短標(biāo)題給你要轉(zhuǎn)變成的狀態(tài)肤粱。(譯者注:現(xiàn)在大多數(shù)瀏覽器不支持或者忽略這個(gè)參數(shù),最好用null代替)

URL — 這個(gè)參數(shù)提供了新歷史紀(jì)錄的地址厨相。請注意领曼,瀏覽器在調(diào)用pushState()方法后不會(huì)去加載這個(gè)URL,但有可能在之后會(huì)這樣做蛮穿,比如用戶重啟瀏覽器之后庶骄。新的URL不一定要是絕對地址,如果它是相對的践磅,它一定是相對于當(dāng)前的URL单刁。新URL必須和當(dāng)前URL在同一個(gè)源下;否則,pushState() 將丟出異常府适。這個(gè)參數(shù)可選幻碱,如果它沒有被特別標(biāo)注,會(huì)被設(shè)置為文檔的當(dāng)前URL细溅。

  • History.replaceState()

按指定的數(shù)據(jù)褥傍,名稱和URL(如果提供該參數(shù)),更新歷史棧上最新的入口喇聊。這個(gè)數(shù)據(jù)被DOM 進(jìn)行了不透明處理恍风。你可以指定任何可以被序列化的javascript對象。


再度強(qiáng)化認(rèn)識(shí)

上面的敘述讓我們對一些基本要素有些認(rèn)識(shí)誓篱,但是實(shí)操下來不盡如人意朋贬,沒有達(dá)到預(yù)期的理解效果。

一窜骄、popstate用來做什么的锦募?
簡而言之就是HTML5新增的用來控制瀏覽器歷史記錄的api。

二邻遏、過去如何操縱瀏覽器歷史記錄糠亩?
window.history對象虐骑,該對象上包含有l(wèi)ength和state的兩個(gè)值,在它的proto上繼承有back赎线、forward廷没、go等幾個(gè)功能函數(shù)
在popstate之前,我們可以利用back垂寥、forward颠黎、go對history進(jìn)行后退和前進(jìn)操作。

例如:
history.back(); (后退一步滞项,使用history.go(-1)也可實(shí)現(xiàn)后退效果)

弊端:只能操作前進(jìn)后退狭归,但是無法控制前進(jìn)后要去哪,history.length都只會(huì)維持原來的狀態(tài)

三文判、popstate的怎么用过椎?
HTML5的新API擴(kuò)展了window.history,使歷史記錄點(diǎn)更加開放了律杠√读鳎可以存儲(chǔ)當(dāng)前歷史記錄點(diǎn)pushState、替換當(dāng)前歷史記錄點(diǎn)replaceState柜去、監(jiān)聽歷史記錄點(diǎn)popstate灰嫉。

pushState、replaceState兩者用法差不多嗓奢。

使用方法:

history.pushState(data,title,url);
//其中第一個(gè)參數(shù)data是給state的值讼撒;
//第二個(gè)參數(shù)title為頁面的標(biāo)題,但當(dāng)前所有瀏覽器都忽略這個(gè)參數(shù)股耽,傳個(gè)空字符串就好根盒;
//第三個(gè)參數(shù)url是你想要去的鏈接;

replaceState用法類似物蝙,例如:history.replaceState("首頁","",location.href+ "#news");

兩者區(qū)別:pushState會(huì)改變history.length炎滞,而replaceState不改變history.length

通過下圖我們可以對比看出pushState和replaceState的差別(注意看history.length的變化):

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>圖解用HTML5的popstate如何玩轉(zhuǎn)瀏覽器歷史記錄</title>
</head>
<body>


<span class="js-news">新聞</span>
<span class="js-music">音樂</span>
<script>

    var locationHref = location.href;
    document.addEventListener("click", function (event) {
        var target = event.target;
        if (target.className == "js-news") {
            history.pushState("首頁", "", locationHref + "#news");
        } else if (target.className == "js-music") {
            history.pushState("音樂", "", locationHref + "#music");
        }
    });

    /*    document.addEventListener("click",function(event){
     var target = event.target;
     if(target.className == "js-news"){
     history.replaceState("首頁","",locationHref + "#news");
     }else if(target.className == "js-music"){
     history.replaceState("音樂","",locationHref + "#music");
     }
     });*/
    
    window.addEventListener("popstate", function () {
        console.log(history.state);
    })
</script>
</body>
</html>

四、監(jiān)聽瀏覽器狀態(tài)(popstate)變化事件
可以理解為監(jiān)聽瀏覽器后退诬乞、前進(jìn)的操作册赛,只要后退或者前進(jìn)就會(huì)觸發(fā)。在上面的demo中震嫉,我們預(yù)先做了如下操作:打開頁面→點(diǎn)擊“新聞”→點(diǎn)擊“音樂”→再點(diǎn)擊“新聞”森瘪,產(chǎn)生了4個(gè)history記錄。然后監(jiān)聽瀏覽器后退和前進(jìn)的狀態(tài)變化票堵,如下圖所示:


遇到的一些小坑

pushState方法在改變url的同時(shí)向?yàn)g覽器歷史棧中壓入新的歷史記錄扼睬。

接收url的參數(shù)為string類型,用以改變當(dāng)前地址欄的url。需要注意的一點(diǎn)就是這個(gè)參數(shù)不能進(jìn)行跨域悴势,即協(xié)議窗宇,域名措伐,端口必須都是相同的,如果出現(xiàn)跨域的情況担映,即會(huì)提示:

Uncaught DOM Exception: Failed to execute 'pushState' on 'History': A history state object with URL http://www.baidu.com/ cannot be created in a document with origin 'http://commanderXL.com' and URL

Example:

    打開www.baidu.com

    history.pushState(null, null, '?page=1')
    //地址欄變成 www.baidu.com/?page=1
    
    history.pushState(null, null, '#page=2');
    //地址欄變成 www.baidu.com/#page=2

其中replaceState:

    history.replaceState(null, null, '#page=2');

replaceState接收的參數(shù)與pushState相同废士,但是最終的效果是:地址欄url會(huì)根據(jù)接收的參數(shù)而變化叫潦,但是瀏覽器并未在當(dāng)瀏覽歷史棧中增加瀏覽器的歷史記錄蝇完,而是替換當(dāng)前的瀏覽器歷史記錄。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末矗蕊,一起剝皮案震驚了整個(gè)濱河市短蜕,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌傻咖,老刑警劉巖朋魔,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異卿操,居然都是意外死亡警检,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門害淤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來扇雕,“玉大人,你說我怎么就攤上這事窥摄∠夥睿” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵崭放,是天一觀的道長哨苛。 經(jīng)常有香客問我,道長币砂,這世上最難降的妖魔是什么建峭? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮决摧,結(jié)果婚禮上亿蒸,老公的妹妹穿的比我還像新娘。我一直安慰自己蜜徽,他們只是感情好祝懂,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著拘鞋,像睡著了一般砚蓬。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上盆色,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天灰蛙,我揣著相機(jī)與錄音祟剔,去河邊找鬼。 笑死摩梧,一個(gè)胖子當(dāng)著我的面吹牛物延,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播仅父,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼叛薯,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了笙纤?” 一聲冷哼從身側(cè)響起耗溜,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎省容,沒想到半個(gè)月后抖拴,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡腥椒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年阿宅,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片笼蛛。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡洒放,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出伐弹,到底是詐尸還是另有隱情拉馋,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布惨好,位于F島的核電站煌茴,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏日川。R本人自食惡果不足惜蔓腐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望龄句。 院中可真熱鬧回论,春花似錦、人聲如沸分歇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽职抡。三九已至葬燎,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背谱净。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來泰國打工窑邦, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人壕探。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓冈钦,卻偏偏與公主長得像,于是被迫代替她去往敵國和親李请。 傳聞我的和親對象是個(gè)殘疾皇子瞧筛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容