對于 Vue 這類漸進(jìn)式前端開發(fā)框架仰猖,為了構(gòu)建 SPA(單頁面應(yīng)用),需要引入前端路由系統(tǒng),這也就是 Vue-Router 存在的意義盒粮。前端路由的核心,就在于 —— 改變視圖的同時(shí)不會向后端發(fā)出請求奠滑。
為了達(dá)到這一目的丹皱,瀏覽器當(dāng)前提供了以下兩種支持:
1.hash —— 即地址欄 URL 中的 #
符號(此 hash 不是密碼學(xué)里的散列運(yùn)算)。
比如這個(gè) URL:http://www.abc.com/#/hello
宋税,hash 的值為 #/hello
摊崭。它的特點(diǎn)在于:hash 雖然出現(xiàn)在 URL 中,但不會被包括在 HTTP 請求中杰赛,對后端完全沒有影響呢簸,因此改變 hash 不會重新加載頁面。
2.history —— 利用了 HTML5 History Interface 中新增的 pushState()
和 replaceState()
方法乏屯。(需要特定瀏覽器支持)
這兩個(gè)方法應(yīng)用于瀏覽器的歷史記錄棧阔墩,在當(dāng)前已有的 back
、forward
瓶珊、go
的基礎(chǔ)之上,它們提供了對歷史記錄進(jìn)行修改的功能耸彪。只是當(dāng)它們執(zhí)行修改時(shí)伞芹,雖然改變了當(dāng)前的 URL,但瀏覽器不會立即向后端發(fā)送請求。
因此可以說唱较,hash 模式和 history 模式都屬于瀏覽器自身的特性扎唾,Vue-Router 只是利用了這兩個(gè)特性(通過調(diào)用瀏覽器提供的接口)來實(shí)現(xiàn)前端路由。
使用場景
一般場景下南缓,hash 和 history 都可以胸遇,除非你更在意顏值,#
符號夾雜在 URL 里看起來確實(shí)有些不太美麗汉形。
調(diào)用 history.pushState() 相比于直接修改 hash纸镊,存在以下優(yōu)勢:
-
pushState()
設(shè)置的新 URL 可以是與當(dāng)前 URL 同源的任意 URL;而hash
只可修改#
后面的部分概疆,因此只能設(shè)置與當(dāng)前 URL 同文檔的 URL逗威; -
pushState()
設(shè)置的新 URL 可以與當(dāng)前 URL 一模一樣,這樣也會把記錄添加到棧中岔冀;而hash
設(shè)置的新值必須與原來不一樣才會觸發(fā)動作將記錄添加到棧中凯旭; -
pushState()
通過stateObject
參數(shù)可以添加任意類型的數(shù)據(jù)到記錄中;而hash
只可添加短字符串使套; -
pushState()
可額外設(shè)置title
屬性供后續(xù)使用罐呼。
當(dāng)然啦,history
也不是樣樣都好侦高。SPA 雖然在瀏覽器里游刃有余嫉柴,但真要通過 URL 向后端發(fā)起 HTTP 請求時(shí),兩者的差異就來了矫膨。尤其在用戶手動輸入 URL 后回車差凹,或者刷新(重啟)瀏覽器的時(shí)候。
1.hash
模式下侧馅,僅hash
符號之前的內(nèi)容會被包含在請求中危尿,如http://www.abc.com
,因此對于后端來說馁痴,即使沒有做到對路由的全覆蓋谊娇,也不會返回 404 錯(cuò)誤。
2.history
模式下罗晕,前端的 URL 必須和實(shí)際向后端發(fā)起請求的 URL 一致济欢,如http://www.abc.com/book/id
。如果后端缺少對/book/id
的路由處理小渊,將返回 404 錯(cuò)誤法褥。Vue-Router 官網(wǎng)里如此描述:“不過這種模式要玩好,還需要后臺配置支持……所以呢酬屉,你要在服務(wù)端增加一個(gè)覆蓋所有情況的候選資源:如果 URL 匹配不到任何靜態(tài)資源半等,則應(yīng)該返回同一個(gè) index.html 頁面揍愁,這個(gè)頁面就是你 app 依賴的頁面∩倍”