寫在前面:一般 SPA 中前端路由有2種實現方式:html
- window.history
- location.hash
下面就來介紹下這兩種方式具體怎麼實現的前端
1.history基本介紹api
window.history 對象包含瀏覽器的歷史,window.history 對象在編寫時可不使用 window 這個前綴。history是實現SPA前端路由是一種主流方法,它有幾個原始方法:瀏覽器
- history.back() - 與在瀏覽器點擊後退按鈕相同
- history.forward() - 與在瀏覽器中點擊按鈕向前相同
- history.go(n) - 接受一個整數做爲參數,移動到該整數指定的頁面,好比go(1)至關於forward(),go(-1)至關於back(),go(0)至關於刷新當前頁面
- 若是移動的位置超出了訪問歷史的邊界,以上三個方法並不報錯,而是靜默失敗
在HTML5,history對象提出了 pushState() 方法和 replaceState() 方法,這兩個方法能夠用來向歷史棧中添加數據,就好像 url 變化了同樣(過去只有 url 變化歷史棧纔會變化),這樣就能夠很好的模擬瀏覽歷史和前進後退了,如今的前端路由也是基於這個原理實現的。bash
2.history.pushState函數
pushState(stateObj, title, url) 方法向歷史棧中寫入數據,其第一個參數是要寫入的數據對象(不大於640kB),第二個參數是頁面的 title, 第三個參數是 url (相對路徑)。網站
- stateObj :一個與指定網址相關的狀態對象,popstate事件觸發時,該對象會傳入回調函數。若是不須要這個對象,此處能夠填null。
- title:新頁面的標題,可是全部瀏覽器目前都忽略這個值,所以這裏能夠填null。
- url:新的網址,必須與當前頁面處在同一個域。瀏覽器的地址欄將顯示這個網址。
關於pushState,有幾個值得注意的地方:ui
- pushState方法不會觸發頁面刷新,只是致使history對象發生變化,地址欄會有反應,只有當觸發前進後退等事件(back()和forward()等)時瀏覽器纔會刷新
- 這裏的 url 是受到同源策略限制的,防止惡意腳本模仿其餘網站 url 用來欺騙用戶,因此當違背同源策略時將會報錯
3.history.replaceStateurl
replaceState(stateObj, title, url) 和pushState的區別就在於它不是寫入而是替換修改瀏覽歷史中當前紀錄,其他和 pushState如出一轍spa
4.popstate事件
- 定義:每當同一個文檔的瀏覽歷史(即history對象)出現變化時,就會觸發popstate事件。
- 注意:僅僅調用pushState方法或replaceState方法 ,並不會觸發該事件,只有用戶點擊瀏覽器倒退按鈕和前進按鈕,或者使用JavaScript調用back、forward、go方法時纔會觸發。另外,該事件只針對同一個文檔,若是瀏覽歷史的切換,致使加載不一樣的文檔,該事件也不會觸發。
- 用法:使用的時候,能夠爲popstate事件指定回調函數。這個回調函數的參數是一個event事件對象,它的state屬性指向pushState和replaceState方法爲當前URL所提供的狀態對象(即這兩個方法的第一個參數)。
5.history實現spa前端路由代碼
<a class="api a">a.html</a>
<a class="api b">b.html</a>
複製代碼
// 註冊路由
document.querySelectorAll('.api').forEach(item => {
item.addEventListener('click', e => {
e.preventDefault();
let link = item.textContent;
if (!!(window.history && history.pushState)) {
// 支持History API
window.history.pushState({name: 'api'}, link, link);
} else {
// 不支持,可以使用一些Polyfill庫來實現
}
}, false)
});
// 監聽路由
window.addEventListener('popstate', e => {
console.log({
location: location.href,
state: e.state
})
}, false)
複製代碼
popstate監聽函數裏打印的e.state即是history.pushState()裏傳入的第一個參數,在這裏即爲
{name: 'api'}
1.Hash基本介紹
url 中能夠帶有一個 hash http://localhost:9000/#/a.html
window 對象中有一個事件是 onhashchange,如下幾種狀況都會觸發這個事件:
- 直接更改瀏覽器地址,在最後面增長或改變#hash;
- 經過改變location.href或location.hash的值;
- 經過觸發點擊帶錨點的連接;
- 瀏覽器前進後退可能致使hash的變化,前提是兩個網頁地址中的hash值不一樣。
2.Hash實現spa前端路由代碼
// 註冊路由
document.querySelectorAll('.api').forEach(item => {
item.addEventListener('click', e => {
e.preventDefault();
let link = item.textContent;
location.hash = link;
}, false)
});
// 監聽路由
window.addEventListener('hashchange', e => {
console.log({
location: location.href,
hash: location.hash
})
}, false)
複製代碼