1. 程式人生 > 實用技巧 >hash和history兩種模式的區別

hash和history兩種模式的區別

hash和history兩種模式的區別


vue-router(前端路由)有兩種模式,hash模式和history模式,這裡來談談兩者的區別。

  1. hash 就是指 url 尾巴後的 # 號以及後面的字元,history沒有底帶#,外觀上比hash 模式好看些
  2. hash回車重新整理會載入到位址列對應的頁面,history一般就是404掉了
  3. hash 能相容到IE8, history 只能相容到 IE10;
  4. 由於 hash 值變化不會導致瀏覽器向伺服器發出請求,而且 hash 改變會觸發 hashchange 事件(hashchange只能改變 # 後面的url片段);雖然hash路徑出現在URL中,但是不會出現在HTTP請求中,對後端完全沒有影響,因此改變hash值不會重新載入頁面,基本都是使用 hash 來實現前端路由的。

(因為Vue專案是個單頁客戶端應用,如果後臺沒有正確的配置,當用戶在瀏覽器直接訪問 http://localhost:8080/user/id 就會返回 404,這就不好看了。history 模式改變 url 的方式會導致瀏覽器向伺服器傳送請求,這不是我們想看到的,我們需要在伺服器端做處理:如果匹配不到任何靜態資源,則應該始終返回同一個 html 頁面)

history模式URL就要和後端進行一致,所以要改為history也需要後端的配合,否則會報錯。
所以hash模式在每次重新整理頁面時是直接更改“#”後的東西,history每次重新整理會重新像後端請求整個網址,也就是重新請求伺服器。如果後端沒有及時響應,就會報錯404!。history的好處是可以進行修改歷史記錄,並且不會立刻像後端發起請求。不過如果對於專案沒有硬性標準要求,我們可以直接使用hash模式開發。

  5.原理區別

  hash原理:hash通過監聽瀏覽器的onhashchange()事件變化,查詢對應的路由規則

  history原理: 利用H5的 history中新增的兩個API pushState() 和 replaceState() 和一個事件onpopstate監聽URL變化

  1. history模式
    利用了HTML5 History Interface中新增的pushState()和replaceState()方法,這兩個方法應用於瀏覽器的歷史記錄棧,在當前已有的back、forward、go的基礎上,他們提供了對當前瀏覽器進行修改的功能,只是當它們被修改時,雖然瀏覽器的URL發生
    了變化,但是不會立即向後端伺服器傳送請求,但是如果點選重新整理,就會重新向後端伺服器傳送請求。
  2. 使用場景
    一般情況下,vue-router前端路由模式使用history和hash都可以,在美觀上history比hash美觀些,因為hash有自己的特定符號#
    相比於hash,history具有以下優勢:
    *pushState()設定新的URL可以是任意與當前URL同源的URL,而hash只能改變#後面的內容,因此只能設定與當前URL同文檔的URL
    *pushState()設定的URL與當前URL一模一樣時也會被新增到歷史記錄棧中,而hash模式中,#後面的內容必須被修改才會被新增到新的記錄棧中
    *pushState()可以通過stateObject引數新增任意型別的資料到記錄中,而hash只能新增短字串
    *pushState()可額外設定title屬性供後續使用

四、為什麼要有hash和history?

對於 Vue 這類漸進式前端開發框架,為了構建 SPA(單頁面應用),需要引入前端路由系統,這也就是 Vue-Router 存在的意義。前端路由的核心,就在於 —— 改變檢視的同時不會向後端發出請求。

為了達到這一目的,瀏覽器當前提供了以下兩種支援:

  1. hash—— 即位址列 URL 中的#符號(此 hash 不是密碼學裡的雜湊運算)。

比如這個 URL:http://localhost:8080/#/hello,hash 的值為 #/hello。它的特點在於:hash 雖然出現在 URL 中,但不會被包括在 HTTP 請求中,對後端完全沒有影響,因此改變 hash 不會重新載入頁面。

  1. history—— 利用了 HTML5 History Interface 中新增的pushState()和replaceState()方法。(需要特定瀏覽器支援)

這兩個方法應用於瀏覽器的歷史記錄棧,在當前已有的 back、forward、go 的基礎之上,它們提供了對歷史記錄進行修改的功能。只是當它們執行修改時,雖然改變了當前的 URL,但瀏覽器不會立即向後端傳送請求。

因此可以說,hash 模式和 history 模式都屬於瀏覽器自身的特性,Vue-Router 只是利用了這兩個特性(通過呼叫瀏覽器提供的介面)來實現前端路由。

如何使用history模式:(在vue專案的路由配置`src/router/index.js`裡面配置)

new Router({

//去掉地址中的雜湊#

mode:"history", // 還需要後臺做一些配合

五、使用場景:

一般場景下,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 後回車,或者重新整理(重啟)瀏覽器的時候。

    1. hash模式下,僅hash符號之前的內容會被包含在請求中,如http://www.abc.com,因此對於後端來說,即使沒有做到對路由的全覆蓋,也不會返回 404 錯誤。
    2. history模式下,前端的 URL 必須和實際向後端發起請求的 URL 一致,如http://www.abc.com/book/id。如果後端缺少對/book/id的路由處理,將返回 404 錯誤。Vue-Router 官網裡如此描述:“不過這種模式要玩好,還需要後臺配置支援……所以呢,你要在服務端增加一個覆蓋所有情況的候選資源:如果 URL 匹配不到任何靜態資源,則應該返回同一個 index.html 頁面,這個頁面就是你 app 依賴的頁面。”