這篇文章主要是記錄下HTML5中history提供的pushState,?replaceStateAPI。最後透過這些API自己實現(xiàn)小型的路由。
關(guān)於window.history提供的API請參閱Mozilla文檔
其中history提供的pushState和replaceState2個API提供了操作瀏覽器歷史堆疊的方法。
其中pushState:
history.pushState(data, null, '#/page=1'); pushState接收3個參數(shù),第一個參數(shù)為一個obj,表示瀏覽器 第二個參數(shù)是document.title的值,一般設(shè)定為`null` 第三個參數(shù)string,用以改變 當(dāng)前url
pushState方法在改變url的同時向瀏覽器歷史堆疊中壓入新的歷史記錄。
接收url的參數(shù)為string類型,用以改變當(dāng)前地址欄的url.需要注意的一點就是這個參數(shù)不能和跨域,即協(xié)議,域名,端口必須都是相同的,如果出現(xiàn)跨域的情況,即會提示:
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:
打開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會根據(jù)接收到的參數(shù)而變化,但是瀏覽器並未在當(dāng)瀏覽器歷史棧中增加瀏覽器的歷史記錄,而是取代目前的瀏覽器歷史記錄。
透過pushState和replaceState雖然能改變URL,但是不會主動觸發(fā)瀏覽器reload。
window物件也提供popstate方法:
window.addEventListener('popstate', function() { });
這個方法用以監(jiān)聽瀏覽器在不同歷史記錄中進(jìn)行切換,而觸發(fā)對應(yīng)的事件。
在瀏覽器提供的history物件上還有g(shù)o,?back方法,用以模擬使用者點擊瀏覽器的前進(jìn)後退按鈕。在某個web應(yīng)用程式當(dāng)中,例如點擊了標(biāo)籤,發(fā)生了頁面的跳躍。這時呼叫history.back();方法後頁面回退,同時頁面發(fā)生刷新,這時window.onpopstate無法監(jiān)聽這個事件。但如果是透過pushState或replaceState來改變URL且不發(fā)生瀏覽器刷新的話,再使用history.back()或history.go(),這樣popstate事件會被觸發(fā)。
history.pushState({page: 1}, null, '?page=1'); history.pushState({page: 2}, null, '?page=2'); history.back(); //瀏覽器后退 window.addEventListener('popstate', function(e) { //在popstate事件觸發(fā)后,事件對象event保存了當(dāng)前瀏覽器歷史記錄的狀態(tài). //e.state保存了pushState添加的state的引用 console.log(e.state); //輸出 {page: 1} });
PS: 透過pushState在url上新增?page=1可以透過location.search去取得search的內(nèi)容。不過如果透過location.search去改變url的話是會主動觸發(fā)瀏覽器reload的。這個特性可以和下面將的關(guān)於hash的內(nèi)容比較下。
API大致了解了,那麼這些方法可以運用到哪些地方呢?一個比較常用的場景是就在單頁應(yīng)用中,透過這些API完成前端的路由設(shè)計,利用pushState,?replaceState可以改變url同時瀏覽器不刷新,並且透過popstate監(jiān)聽瀏覽器歷史記錄的方式,完成一系列的異步動作。
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(); } } })
大致的實現(xiàn)思路就是,透過添加路由訊息,然後攔截標(biāo)籤的預(yù)設(shè)行為,並與註冊的路由資訊進(jìn)行匹配。若符合成功呼叫對應(yīng)的handle方法.
不過pushState和replaceState方法在低版本的IE瀏覽器下相容性不是很好。所以可以進(jìn)行降級使用hash來進(jìn)行路由設(shè)計。
hash?請戳我。
可以透過location.hash取得url上第一個#(fragment)及後面的內(nèi)容。同時也能透過location.hash改寫其內(nèi)容,且不會主動觸發(fā)瀏覽器reload。 有些功能是不是跟pushState和replaceState一樣? 所以為了相容到低版本的瀏覽器,可以透過監(jiān)聽#變化來進(jìn)行路由設(shè)計。
那麼如何去監(jiān)聽呢? 比較粗暴的一種方式就是polling。
var oldHash = location.hash; setTimeInterval(function() { if(oldHash !== location.hash) { //do something oldHash = location.hash; } }, 100);
不過,H5也提供了一個API:?hashchange。它的就可以直接取代上面的polling方法,來監(jiān)聽#的變化。
window.addEventListener('hashchange', function() { routeHandle(locaiton.hash); });
這個小型的路由設(shè)計可以參考我的github.
稍微總結(jié)下:
上面主要介紹了history提供的一些API,hash的相關(guān)知識。在平時可以運用到SPA當(dāng)中,Gmail就是透過hash來進(jìn)行路由設(shè)計的。它相對於頁面跳轉(zhuǎn)來說:
頁面只需要載入一次。後面的頁面切換可以透過ajax去請求資料。頁面體驗更加流暢;
可以利用本地緩存,優(yōu)化頁面體驗。在不同頁面切換的過程中更加流暢;
可進(jìn)行隨選載入...
等等一些實用的好處吧。

熱AI工具

Undress AI Tool
免費脫衣圖片

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

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

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

禪工作室 13.0.1
強大的PHP整合開發(fā)環(huán)境

Dreamweaver CS6
視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)
