細說前端路由的hash模式和 history模式

這是我參與8月更文挑戰的第6天,活動詳情查看:8月更文挑戰html

目錄

爲何要用

前端路由實現方式

1.hash模式

2.history模式


爲何要用

AJAX局部刷新,致使瀏覽器的URL不會發生任何變化而完成了請求,從而破壞了用戶瀏覽體驗。同時本次瀏覽的頁面內容在用戶下次使用URL訪問時將沒法從新呈現,使用路由能夠很好地解決這個問題。前端

單頁面應用利用了JavaScript動態變換網頁內容,避免了頁面重載;路由則提供了瀏覽器地址變化,網頁內容也跟隨變化,二者結合起來則爲咱們提供了體驗良好的單頁面web應用。web

前端路由實現方式

在單頁面web網頁中, 單純的瀏覽器地址改變, 網頁不會重載,如單純的hash網址改變網頁不會變化,所以咱們的路由主要是經過監聽事件,並利用js實現動態改變網頁內容,有兩種實現方式:後端

hash模式:監聽瀏覽器地址hash值變化,執行相應的js切換網頁;跨域

history模式:利用history API實現url地址改變,網頁內容改變; 它們的區別最明顯的就是hash會在瀏覽器地址後面增長#號,而history能夠自定義地址。瀏覽器

1.hash模式

使用window.location.hash屬性及窗口的onhashchange事件,能夠實現監聽瀏覽器地址hash值變化,執行相應的js切換網頁。下面具體介紹幾個使用過程當中必須理解的要點:緩存

  1. hash指的是地址中#號以及後面的字符,也稱爲散列值。hash也稱做錨點,自己是用來作頁面跳轉定位的。如http://localhost/index.html#abc,這裏的#abc就是hash;安全

  2. 散列值是不會隨請求發送到服務器端的,因此改變hash,不會從新加載頁面;服務器

  3. 監聽 window 的 hashchange 事件,當散列值改變時,能夠經過 location.hash 來獲取和設置hash值;markdown

  4. location.hash值的變化會直接反應到瀏覽器地址欄;

觸發hashchange事件的幾種狀況:

  • 瀏覽器地址欄散列值的變化(包括瀏覽器的前進、後退)會觸發window.location.hash值的變化,從而觸發onhashchange事件;

  • 當瀏覽器地址欄中URL包含哈希如 http://www.baidu.com/#home,這時按下輸入,瀏覽器發送http://www.baidu.com/請求至服務器,請求完畢以後設置散列值爲#home,進而觸發onhashchange事件;

  • 當只改變瀏覽器地址欄URL的哈希部分,這時按下回車,瀏覽器不會發送任何請求至服務器,這時發生的只是設置散列值新修改的哈希值,並觸發onhashchange事件;

  • html中<a>標籤的屬性 href 能夠設置爲頁面的元素ID如 #top,當點擊該連接時頁面跳轉至該id元素所在區域,同時瀏覽器自動設置 window.location.hash 屬性,地址欄中的哈希值也會發生改變,並觸發onhashchange事件;

//設置 url 的 hash,會在當前url後加上'#abc'
window.location.hash='abc';
let hash = window.location.hash //'#abc'

window.addEventListener('hashchange',function(){
	//監聽hash變化,點擊瀏覽器的前進後退會觸發
})

複製代碼

2.history模式

概述

window.history 屬性指向 History 對象,它表示當前窗口的瀏覽歷史。當發生改變時,只會改變頁面的路徑,不會刷新頁面。 History 對象保存了當前窗口訪問過的全部頁面網址。經過 history.length 能夠得出當前窗口一共訪問過幾個網址。 因爲安全緣由,瀏覽器不容許腳本讀取這些地址,可是容許在地址之間導航。 瀏覽器工具欄的「前進」和「後退」按鈕,其實就是對 History 對象進行操做。

屬性

History 對象主要有兩個屬性。

  • History.length:當前窗口訪問過的網址數量(包括當前網頁)
  • History.state:History 堆棧最上層的狀態值(詳見下文)
// 當前窗口訪問過多少個網頁
history.length // 1

// History 對象的當前狀態
// 一般是 undefined,即未設置
history.state // undefined
複製代碼

方法

History.back()、History.forward()、History.go() 這三個方法用於在歷史之中移動。

  • History.back():移動到上一個網址,等同於點擊瀏覽器的後退鍵。對於第一個訪問的網址,該方法無效果。
  • History.forward():移動到下一個網址,等同於點擊瀏覽器的前進鍵。對於最後一個訪問的網址,該方法無效果。
  • History.go():接受一個整數做爲參數,以當前網址爲基準,移動到參數指定的網址。若是參數超過實際存在的網址範圍,該方法無效果;若是不指定參數,默認參數爲0,至關於刷新當前頁面。
history.back();
history.forward();
history.go(1);//至關於history.forward()
history.go(-1);//至關於history.back()
history.go(0); // 刷新當前頁面
複製代碼

注意:移動到之前訪問過的頁面時,頁面一般是從瀏覽器緩存之中加載,而不是從新要求服務器發送新的網頁。

History.pushState()

該方法用於在歷史中添加一條記錄。pushState()方法不會觸發頁面刷新,只是致使 History 對象發生變化,地址欄會有變化。

語法:history.pushState(object, title, url)

該方法接受三個參數,依次爲:

  • object:是一個對象,經過 pushState 方法能夠將該對象內容傳遞到新頁面中。若是不須要這個對象,此處能夠填 null。
  • title:指標題,幾乎沒有瀏覽器支持該參數,傳一個空字符串比較安全。
  • url:新的網址,必須與當前頁面處在同一個域。不指定的話則爲當前的路徑,若是設置了一個跨域網址,則會報錯。
var data = { foo: 'bar' };
history.pushState(data, '', '2.html');
console.log(history.state) // {foo: "bar"}
複製代碼

注意:若是 pushState 的 URL 參數設置了一個新的錨點值(即 hash),並不會觸發 hashchange 事件。反過來,若是 URL 的錨點值變了,則會在 History 對象建立一條瀏覽記錄。

若是 pushState() 方法設置了一個跨域網址,則會報錯。

// 報錯
// 當前網址爲 http://example.com
history.pushState(null, '', 'https://twitter.com/hello');
複製代碼

上面代碼中,pushState 想要插入一個跨域的網址,致使報錯。這樣設計的目的是,防止惡意代碼讓用戶覺得他們是在另外一個網站上,由於這個方法不會致使頁面跳轉。

History.replaceState() 該方法用來修改 History 對象的當前記錄,用法與 pushState() 方法同樣。

假定當前網頁是 example.com/example.html。

history.pushState({page: 1}, '', '?page=1')
// URL 顯示爲 http://example.com/example.html?page=1

history.pushState({page: 2}, '', '?page=2');
// URL 顯示爲 http://example.com/example.html?page=2

history.replaceState({page: 3}, '', '?page=3');
// URL 顯示爲 http://example.com/example.html?page=3

history.back()
// URL 顯示爲 http://example.com/example.html?page=1

history.back()
// URL 顯示爲 http://example.com/example.html

history.go(2)
// URL 顯示爲 http://example.com/example.html?page=3
複製代碼

popstate 事件

每當 history 對象出現變化時,就會觸發 popstate 事件。

注意:

僅僅調用pushState()方法或replaceState()方法 ,並不會觸發該事件; 只有用戶點擊瀏覽器倒退按鈕和前進按鈕,或者使用 JavaScript 調用History.back()、History.forward()、History.go()方法時纔會觸發。 另外,該事件只針對同一個文檔,若是瀏覽歷史的切換,致使加載不一樣的文檔,該事件也不會觸發。 頁面第一次加載的時候,瀏覽器不會觸發popstate事件。 使用的時候,能夠爲popstate事件指定回調函數,回調函數的參數是一個 event 事件對象,它的 state 屬性指向當前的 state 對象。

window.addEventListener('popstate', function(e) {
	//e.state 至關於 history.state
	console.log('state: ' + JSON.stringify(e.state));
	console.log(history.state);
});
複製代碼

點擊查看 經過history.pushState 實現頁面 tab 切換的功能。

history 致命的缺點就是當改變頁面地址後,強制刷新瀏覽器時,(若是後端沒有作準備的話)會報錯,由於刷新是拿當前地址去請求服務器的,若是服務器中沒有相應的響應,會出現 404 頁面。


若是這篇文章幫到了你,記得點贊👍收藏加關注哦😊,但願點贊多多多多...

文中若有錯誤,歡迎在評論區指正

相關文章
相關標籤/搜索