這篇文章主要是記錄下HTML5中history提供的pushState,?replaceStateAPI。最后通過(guò)這些API自己實(shí)現(xiàn)小型的路由。
關(guān)于window.history提供的API請(qǐng)參見(jiàn)Mozilla文檔
其中history提供的pushState和replaceState2個(gè)API提供了操作瀏覽器歷史棧的方法。
其中pushState:
history.pushState(data, null, '#/page=1'); pushState接收3個(gè)參數(shù),第一個(gè)參數(shù)為一個(gè)obj,表示瀏覽器 第二個(gè)參數(shù)是document.title的值,一般設(shè)定為`null` 第三個(gè)參數(shù)string,用以改變 當(dāng)前url
pushState方法在改變url的同時(shí)向?yàn)g覽器歷史棧中壓入新的歷史記錄。
接收url的參數(shù)為string類型,用以改變當(dāng)前地址欄的url.需要注意的一點(diǎn)就是這個(gè)參數(shù)不能和跨域,即協(xié)議,域名,端口必須都是相同的,如果出現(xiàn)跨域的情況,即會(huì)提示:
Uncaught DOMException: 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:
打開(kāi)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)前的瀏覽器歷史記錄。
通過(guò)pushState和replaceState雖然能改變URL,但是不會(huì)主動(dòng)觸發(fā)瀏覽器reload。
window對(duì)象還提供popstate方法:
window.addEventListener('popstate', function() { });
這個(gè)方法用以監(jiān)聽(tīng)瀏覽器在不同歷史記錄中進(jìn)行切換,而觸發(fā)相應(yīng)的事件。
在瀏覽器提供的history對(duì)象上還有g(shù)o, back方法,用以模擬用戶點(diǎn)擊瀏覽器的前進(jìn)后退按鈕。在某個(gè)web應(yīng)用當(dāng)中,比如點(diǎn)擊了標(biāo)簽,發(fā)生了頁(yè)面的跳轉(zhuǎn)。這時(shí)調(diào)用history.back();方法后頁(yè)面回退,同時(shí)頁(yè)面發(fā)生刷新,這時(shí)window.onpopstate無(wú)法監(jiān)聽(tīng)這個(gè)事件。但是如果是通過(guò)pushState或者replaceState來(lái)改變URL且不發(fā)生瀏覽器刷新的話,再使用history.back()或history.go(),這樣popstate事件會(huì)被觸發(fā)。
history.pushState({page: 1}, null, '?page=1'); history.pushState({page: 2}, null, '?page=2'); history.back(); //瀏覽器后退 window.addEventListener('popstate', function(e) { //在popstate事件觸發(fā)后,事件對(duì)象event保存了當(dāng)前瀏覽器歷史記錄的狀態(tài). //e.state保存了pushState添加的state的引用 console.log(e.state); //輸出 {page: 1} });
PS: 通過(guò)pushState在url上添加?page=1可以通過(guò)location.search去獲取search的內(nèi)容。不過(guò)如果通過(guò)location.search去改變url的話是會(huì)主動(dòng)觸發(fā)瀏覽器reload的。這個(gè)特性可以和下面將的關(guān)于hash的內(nèi)容對(duì)比下。
API大致了解了,那么這些方法可以運(yùn)用到哪些地方呢?一個(gè)比較常用的場(chǎng)景是就在單頁(yè)應(yīng)用中,通過(guò)這些API完成前端的路由設(shè)計(jì),利用pushState, replaceState可以改變url同時(shí)瀏覽器不刷新,并且通過(guò)popstate監(jiān)聽(tīng)瀏覽器歷史記錄的方式,完成一系列的異步動(dòng)作。
addRoute('/login', function() { //do something }) //路由處理 const routeHandle = (path) => { Router.forEach((item, index) => { if(item.path === path) { item.handle.apply(null, [path]); return true; } }) return false; } //攔截默認(rèn)的a標(biāo)簽行為 document.addEventListener('click', function(e) { let dataset = e.target.dataset; if(dataset) { if(routeHandle(dataset.href)) { //阻止默認(rèn)行為 e.preventDefault(); } } })
大致的實(shí)現(xiàn)思路就是,通過(guò)添加路由信息,然后攔截標(biāo)簽的默認(rèn)行為,并與注冊(cè)的路由信息進(jìn)行匹配。若匹配成功調(diào)用對(duì)應(yīng)的handle方法.
不過(guò)pushState和replaceState方法在低版本的IE瀏覽器下兼容性不是很好。所以可以進(jìn)行降級(jí)使用hash來(lái)進(jìn)行路由設(shè)計(jì)。
hash?請(qǐng)戳我。
可以通過(guò)location.hash獲取url上第一個(gè)#(fragment)及后面的內(nèi)容。同時(shí)還能通過(guò)location.hash改寫(xiě)其內(nèi)容,且不會(huì)主動(dòng)觸發(fā)瀏覽器reload。 有些功能是不是和pushState和replaceState一樣? 所以為了兼容到低版本的瀏覽器,可以通過(guò)監(jiān)聽(tīng)#變化來(lái)進(jìn)行路由設(shè)計(jì)。
那么如何去監(jiān)聽(tīng)呢? 比較粗暴的一種方式就是polling。
var oldHash = location.hash; setTimeInterval(function() { if(oldHash !== location.hash) { //do something oldHash = location.hash; } }, 100);
不過(guò),H5還提供了一個(gè)API: hashchange。它的就可以直接代替上面的polling方法,來(lái)監(jiān)聽(tīng)#的變化。
window.addEventListener('hashchange', function() { routeHandle(locaiton.hash); });
這個(gè)小型的路由設(shè)計(jì)可以參見(jiàn)我的github.
稍微總結(jié)下:
上面主要介紹了history提供的一些API,hash的相關(guān)知識(shí)。在平時(shí)可以運(yùn)用到SPA當(dāng)中,Gmail就是通過(guò)hash來(lái)進(jìn)行路由設(shè)計(jì)的。它相對(duì)于頁(yè)面跳轉(zhuǎn)來(lái)說(shuō):
頁(yè)面只需要加載一次。后面的頁(yè)面切換可以通過(guò)ajax去請(qǐng)求數(shù)據(jù)。頁(yè)面體驗(yàn)更加流暢;
可以利用本地緩存,優(yōu)化頁(yè)面體驗(yàn)。在不同頁(yè)面切換的過(guò)程中更加流暢;
可進(jìn)行按需加載...
等等一些實(shí)用的好處吧。

熱AI工具

Undress AI Tool
免費(fèi)脫衣服圖片

Undresser.AI Undress
人工智能驅(qū)動(dòng)的應(yīng)用程序,用于創(chuàng)建逼真的裸體照片

AI Clothes Remover
用于從照片中去除衣服的在線人工智能工具。

Clothoff.io
AI脫衣機(jī)

Video Face Swap
使用我們完全免費(fèi)的人工智能換臉工具輕松在任何視頻中換臉!

熱門(mén)文章

熱工具

記事本++7.3.1
好用且免費(fèi)的代碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
功能強(qiáng)大的PHP集成開(kāi)發(fā)環(huán)境

Dreamweaver CS6
視覺(jué)化網(wǎng)頁(yè)開(kāi)發(fā)工具

SublimeText3 Mac版
神級(jí)代碼編輯軟件(SublimeText3)