在瞭解路由模式前,我們先看下 什麼是單頁面應用,vue-router 的實現原理是怎樣的,這樣更容易理解路由。
SPA與前端路由
SPA(單頁面應用,全程為:Single-page Web applications)指的是隻有一張Web頁面的應用,是載入單個HTML 頁面並在使用者與應用程式互動時動態更新該頁面的Web應用程式,簡單通俗點就是在一個專案中只有一個html頁面,它在第一次載入頁面時,將唯一完成的html頁面和所有其餘頁面元件一起下載下來,所有的元件的展示與切換都在這唯一的頁面中完成,這樣切換頁面時,不會重新載入整個頁面,而是通過路由來實現不同元件之間的切換。
單頁面應用(SPA)的核心之一是:更新檢視而不重新請求頁面。
vue Router實現原理
vue-router 在實現單頁面路由時,提供了兩種方式:Hash 模式和 History 模式;vue2是 根據 mode 引數來決定採用哪種方式,預設是 Hash 模式,手動設定為 History 模式。更新檢視但不重新請求頁面”是前端路由原理的核心之一,目前在瀏覽器環境中這一功能的實現主要有以下兩種方式
Hash
簡述
- vue-router 預設為hash模式,使用URL的 hash 來模擬一個完整的URL,當URL改變時,頁面不會重新載入;# 就是 hash符號,中文名為雜湊符或者錨點,在 hash 符號後的值稱為 hash 值。
- 路由的 hash 模式是利用了 window可以監聽onhashchange 事件來實現的,也就是說 hash 值是用來指導瀏覽器動作的,對伺服器沒有影響,HTTP 請求中也不會包括 hash 值,同時每一次改變 hash 值,都會在瀏覽器的訪問歷史中增加一個記錄,使用“後退”按鈕,就可以回到上一個位置。所以,hash模式 是根據 hash 值 來發生改變,根據不同的值,渲染指定DOM位置的不同資料。
特點
- url中帶一個 # 號
- 可以改變URL,但不會觸發頁面重新載入(hash的改變會記錄在 window.hisotry 中)因此並不算是一次http請求,所以這種模式不利於SEO優化
- 只能修改 # 後面的部分,因此只能跳轉與當前URL同文件的URL
- 只能通過字串改變URL
- 通過 window.onhashchange 監聽 hash 的改變,藉此實現無重新整理跳轉的功能。
- 每改變一次 hash ( window.location.hash),都會在瀏覽器的訪問歷史中增加一個記錄。
- 路徑中從 # 開始,後面的所有路徑都叫做路由的
雜湊值,
並且雜湊值它不會作為路徑的一部分隨著http請求,發給伺服器
History
簡述
- history 是路由的另一種模式,在相應的 router 配置時將 mode 設定為 history 即可。
- history 模式是通過呼叫 window.history 物件上的一系列方法來實現頁面的無重新整理跳轉。
- 利用了 HTML5 History Interface 中新增的 pushState() 和 replaceState() 方法。
- 這兩個方法應用於瀏覽器的歷史記錄棧,在當前已有的 back、forward、go 的基礎之上,它們提供了對歷史記錄進行修改的功能。只是當它們執行修改時,雖然改變了當前的 URL,但瀏覽器不會立即向後端傳送請求。
特點
- 新的URL可以是與當前URL同源的任意 URL,也可以與當前URL一樣,但是這樣會把重複的一次操作記錄到棧中。
- 通過引數stateObject可以新增任意型別的資料到記錄中。
- 可額外設定title屬性供後續使用。
- 通過pushState、replaceState實現無重新整理跳轉的功能。
- 路徑直接拼接在埠號後面,後面的路徑也會隨著http請求發給伺服器,因此前端的URL必須和向傳送請求後端URL保持一致,否則會報404錯誤。
- 由於History API的緣故,低版本瀏覽器有相容行問題。
生產環境存在問題
因為 history 模式的時候路徑會隨著 http 請求傳送給伺服器,專案打包部署時,需要後端配置 nginx,當應用通過 vue-router 跳轉到某個頁面後,因為此時是前端路由控制頁面跳轉,雖然url改變,但是頁面只是內容改變,並沒有重新請求,所以這套流程沒有任何問題。但是,如果在當前的頁面重新整理一下,此時會重新發起請求,如果 nginx 沒有匹配到當前url,就會出現404的頁面。
上文已講,hash 雖然可以改變URL,但不會被包括在 HTTP 請求中。它被用來指導瀏覽器動作,並不影響伺服器端,因此,改變 hash 並沒有改變URL,所以頁面路徑還是之前的路徑,nginx 不會攔截。 因此,切記在使用 history 模式時,需要服務端允許地址可訪問,否則就會出現404的尷尬場景。
那為什麼開發環境時就不會出現404呢?
因為在 vue-cli
中 webpack
幫我們做了處理
解決問題
生產環境 重新整理 404 的解決辦法可以在 nginx
做代理轉發,在 nginx 中配置按順序檢查引數中的資源是否存在,如果都沒有找到,讓 nginx 內部重定向到專案首頁。
參考:Vue 瞭解前端路由 hash 與 history 差異