vue中mode hash 和 history的區別
對於 Vue 這類漸進式前端開發框架,為了構建 SPA(單頁面應用),需要引入前端路由系統,這也就是 Vue-Router 存在的意義。前端路由的核心,就在於 —— 改變檢視的同時不會向後端發出請求。
為了達到這一目的,瀏覽器當前提供了以下兩種支援:
- hash —— 即位址列 URL 中的
#
符號(此 hash 不是密碼學裡的雜湊運算)。
比如這個 URL:http://www.abc.com/#/hello
,hash 的值為#/hello
。它的特點在於:hash 雖然出現在 URL 中,但不會被包括在 HTTP 請求中,對後端完全沒有影響,因此改變 hash 不會重新載入頁面。 - history —— 利用了 HTML5 History Interface 中新增的
pushState()
replaceState()
方法。(需要特定瀏覽器支援)
這兩個方法應用於瀏覽器的歷史記錄棧,在當前已有的back
、forward
、go
的基礎之上,它們提供了對歷史記錄進行修改的功能。只是當它們執行修改時,雖然改變了當前的 URL,但瀏覽器不會立即向後端傳送請求。
因此可以說,hash 模式和 history 模式都屬於瀏覽器自身的特性,Vue-Router 只是利用了這兩個特性(通過呼叫瀏覽器提供的介面)來實現前端路由。
使用場景
一般場景下,hash 和 history 都可以,除非你更在意顏值,#
符號夾雜在 URL 裡看起來確實有些不太美麗。
如果不想要很醜的 hash,我們可以用路由的 history 模式,這種模式充分利用 history.pushState API 來完成
URL 跳轉而無須重新載入頁面。——Vue-router 官網。
另外,根據 Mozilla Develop Network 的介紹,呼叫 history.pushState()
相比於直接修改 hash
,存在以下優勢:
pushState()
設定的新 URL 可以是與當前 URL 同源的任意 URL;而hash
只可修改#
後面的部分,因此只能設定與當前 URL 同文檔的 URL;pushState()
設定的新 URL 可以與當前 URL 一模一樣,這樣也會把記錄新增到棧中;而hash
設定的新值必須與原來不一樣才會觸發動作將記錄新增到棧中;pushState()
通過stateObject
引數可以新增任意型別的資料到記錄中;而hash
pushState()
可額外設定title
屬性供後續使用。
當然啦,history
也不是樣樣都好。SPA 雖然在瀏覽器裡遊刃有餘,但真要通過 URL 向後端發起 HTTP 請求時,兩者的差異就來了。尤其在使用者手動輸入 URL 後回車,或者重新整理(重啟)瀏覽器的時候。
hash
模式下,僅hash
符號之前的內容會被包含在請求中,如http://www.abc.com
,因此對於後端來說,即使沒有做到對路由的全覆蓋,也不會返回 404 錯誤。history
模式下,前端的 URL 必須和實際向後端發起請求的 URL 一致,如http://www.abc.com/book/id
。如果後端缺少對/book/id
的路由處理,將返回 404 錯誤。Vue-Router 官網裡如此描述:“不過這種模式要玩好,還需要後臺配置支援……所以呢,你要在服務端增加一個覆蓋所有情況的候選資源:如果 URL 匹配不到任何靜態資源,則應該返回同一個 index.html 頁面,這個頁面就是你 app 依賴的頁面。”
history模式怕啥
通過history api,我們丟掉了醜陋的#,但是它也有個毛病:
不怕前進,不怕後退,就怕重新整理,f5,(如果後端沒有準備的話),因為重新整理是實實在在地去請求伺服器的,不玩虛的。
在hash模式下,前端路由修改的是#中的資訊,而瀏覽器請求時是不帶它玩的,所以沒有問題.但是在history下,你可以自由的修改path,當重新整理時,如果伺服器中沒有相應的響應或者資源,會分分鐘刷出一個404來。
小結
結合自身例子,對於一般的 Vue + Vue-Router + Webpack + XXX 形式的 Web 開發場景,用 history
模式即可,只需在後端(Apache 或 Nginx)進行簡單的路由配置,同時搭配前端路由的 404 頁面支援。