1. 程式人生 > >vue 路由裏面的 hash 和 history

vue 路由裏面的 hash 和 history

() 符號 evel inter 發送請求 回車 bpa 也不會 部分

對於 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 頁面支持。
---------------------
<2>

在說vue路由鉤子函數之前,我先介紹一下路由的兩種模式:

const router = new VueRouter({
   mode: ‘history‘,
  mode: ‘hash‘,
})


1.hash模式
hash模式背後的原理是onhashchange事件,可以用window.onhashchange來監聽這個事件,hash模式中的hash值是不會傳到後臺的,所以服務器端做一個根地址的映射就可以了。


2.history模式
history利用了 HTML5 History Interface 中新增的 pushState() 和 replaceState() 方法。這兩個方法應用於瀏覽器的歷史記錄棧,在當前已有的 back、forward、go 的基礎之上,它們提供了對歷史記錄進行修改的功能。只是當它們執行修改時,雖然改變了當前的 URL,但瀏覽器不會立即向後端發送請求。


3.總結

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 依賴的頁面。

---------------------
<3>

主要是因為活動頁會存在pc端的時候未登錄的用戶也需要訪問的問題,因為未登錄用戶在活動頁面進行操作的時候會觸發到登錄事件,然後我們實現的方式是通過接口來判斷,該接口標記的是一個upn的值
然後登錄的時候是單點登錄,不知道是否回調地址不支持vue形式下hash模式的路由,因而自動忽視了後面的#路徑
然後我查了一下一般回調以後#後都會默認為書簽,我轉義了然而還是只能職別#之前的路徑
由於不是很清楚登錄單點那一塊而且他們暫時實現沒有什麽業務問題(當然開始~~就是不穩定,現在有時候還是會有不穩定的問題)所以暫時不存在讓他們的回調地址支持vue的hash模式路由的問題
然後我就只能修改vue Router的路由模式,修改為了hostory模式
好吧,摸索了很久不然可能真的沒有辦法解決
運維部署的活動地址線上的路徑是 https://xxxxx.xxxxl.com/activity
我做了兩處修改


1、修改模式
2、切到網站路徑下的/activity
3、其它路徑切到/activity/

當然這麽處理以後本地運行出來肯定是白板。因為方便我一般是切到文件夾下直接 run的
沒有再本地使用搭建本地的所以,需要兩份路由一份只修改模式,一份繼修改模式又切換路徑
然後這樣只是代碼上的處理我們還需要修改服務端的配置
基於運維良好的配合,才能嘗試出來,很是開心

他們本來對活動做的配置


參考router官方文檔https://router.vuejs.org/zh-cn/essentials/history-mode.html
使用 try命令嘗試多種配置
location / { try_files $uri $uri/ /index.html; }

然後完成這些設置以後線上終於可以訪問 https://xxxxx.xxxxx.com/activity/valentine
這種路徑的形式了,當然這個地址是實際存在的,它並不會跳轉到配置的路由的首頁

vue 路由裏面的 hash 和 history