淺談前端路由原理hash和history

這是我參與 8 月更文挑戰的第 8 天,活動詳情查看: 8月更文挑戰html

🎹序言

衆所周知, hashhistory 在前端面試中是很常考的一道題目。在學習本文內容以前,週一對 hashhistory 的認知可能就在 hashurl 裏面多了個 # ,而 history 就不會。而後,我認知裏還有一個是隻有 history 才能作先後端分離,而 hash 跟先後端分離沒有關係。然而,現實是……前端

嚇到跌倒

對於前端路由來講, hashhistory 均可以用於先後端分離項目,且二者有各自的特色和各自的使用場景,在使用過程當中主要要了解當前項目所處的場景,以便於更好地判斷使用哪種路由模式更佳。下面進入本文的講解~😜vue

🎸1、前端路由原理

一、SPA

SPA,即單頁面應用(Single Page Application)。所謂單頁 Web 應用,就是隻有一張 Web 頁面的應用。單頁應用程序 (SPA) 是加載單個 HTML 頁面並在用戶與應用程序交互時動態更新該頁面的 Web 應用程序。瀏覽器一開始會加載必需的 HTMLCSSJavaScript ,全部的操做都在這張頁面上完成,都由 JavaScript 來控制。react

現現在,爲了配合單頁面 Web 應用快速發展的節奏,各種前端組件化技術棧層出不窮。近幾年來,經過不斷的版本迭代, vuereact 兩大技術棧脫穎而出,成爲當下最受歡迎的兩大技術棧。nginx

二、何時須要路由

對於現代開發的項目來講,稍微複雜一點的 SPA ,都須要用到路由。而 vue-router 正是 vue 的路由標配,且 vue-router兩種模式hashhistorygit

下面就依據這兩種模式來進行一一講解。github

🎷2、Hash模式

一、定義

hash 模式是一種把前端路由的路徑用井號 # 拼接在真實 url 後面的模式。當井號 # 後面的路徑發生變化時,瀏覽器並不會從新發起請求,而是會觸發 onhashchange 事件。面試

二、網頁url組成部分

(1)瞭解幾個url的屬性

屬性 含義
location.protocal 協議
location.hostname 主機名
location.host 主機
location.port 端口號
location.patchname 訪問頁面
location.search 搜索內容
location.hash 哈希值

(2)演示

下面用一個網址來演示以上屬性:vue-router

//http://127.0.0.1:8001/01-hash.html?a=100&b=20#/aaa/bbb
location.protocal // 'http:'
localtion.hostname // '127.0.0.1'
location.host // '127.0.0.1:8001'
location.port //8001
location.pathname //'01-hash.html'
location.serach // '?a=100&b=20'
location.hash // '#/aaa/bbb'
複製代碼

三、hash的特色

  • hash變化會觸發網頁跳轉,即瀏覽器的前進和後退。後端

  • hash 能夠改變 url ,可是不會觸發頁面從新加載(hash的改變是記錄在 window.history 中),即不會刷新頁面。也就是說,全部頁面的跳轉都是在客戶端進行操做。所以,這並不算是一次 http 請求,因此這種模式不利於 SEO 優化。hash 只能修改 # 後面的部分,因此只能跳轉到與當前 url 同文檔的 url

  • hash 經過 window.onhashchange 的方式,來監聽 hash 的改變,藉此實現無刷新跳轉的功能。

  • hash 永遠不會提交到 server 端(能夠理解爲只在前端自生自滅)。

🎺3、History模式

一、定義

history APIH5 提供的新特性,容許開發者直接更改前端路由,即更新瀏覽器 URL 地址而不從新發起請求

二、與hash的區別

咱們用一個例子來演示, hashhistory 在瀏覽器下刷新時的區別。具體以下:

正常頁面瀏覽

https://github.com/xxx 刷新頁面

https://github.com/xxx/yyy 刷新頁面

https://github.com/xxx/yyy/zzz 刷新頁面
複製代碼

改造H5 history模式

https://github.com/xxx 刷新頁面

https://github.com/xxx/yyy 前端跳轉,不刷新頁面

https://github.com/xxx/yyy/zzz 前端跳轉,不刷新頁面
複製代碼

三、history的API

下面闡述幾種 HTML5 新增的 history API具體以下表:

API 定義
history.pushState(data, title [, url]) pushState主要用於往歷史記錄堆棧頂部添加一條記錄。各參數解析以下:①data會在onpopstate事件觸發時做爲參數傳遞過去;②title爲頁面標題,當前全部瀏覽器都會忽略此參數;③url爲頁面地址,可選,缺乏時表示爲當前頁地址
history.replaceState(data, title [, url]) 更改當前的歷史記錄,參數同上; 上面的pushState是添加,這個更改
history.state 用於存儲以上方法的data數據,不一樣瀏覽器的讀寫權限不同
window.onpopstate 響應pushState或者replaceState的調用

四、history的特色

對於 history 來講,主要有如下特色:

  • 新的 url 能夠是與當前 url 同源的任意 url ,也能夠是與當前 url 同樣的地址,可是這樣會致使的一個問題是,會把重複的這一次操做記錄到棧當中。
  • 經過 history.state ,添加任意類型的數據到記錄中。
  • 能夠額外設置 title 屬性,以便後續使用。
  • 經過 pushStatereplaceState 來實現無刷新跳轉的功能。

五、存在問題

對於 history 來講,確實解決了很多 hash 存在的問題,可是也帶來了新的問題。具體以下:

  • 使用 history 模式時,在對當前的頁面進行刷新時,此時瀏覽器會從新發起請求。若是 nginx 沒有匹配獲得當前的 url ,就會出現 404 的頁面。
  • 而對於 hash 模式來講, 它雖然看着是改變了 url ,但不會被包括在 http 請求中。因此,它算是被用來指導瀏覽器的動做,並不影響服務器端。所以,改變 hash 並無真正地改變 url ,因此頁面路徑仍是以前的路徑, nginx 也就不會攔截。
  • 所以,在使用 history 模式時,須要經過服務端來容許地址可訪問,若是沒有設置,就很容易致使出現 404 的局面。

六、二者選擇

下面咱們再來介紹下在實際的項目中,如何對這二者進行選擇。具體以下:

  • to B 的系統推薦用 hash ,相對簡單且容易使用,且由於 hashurl 規範不敏感;
  • to C 的系統,能夠考慮選擇 H5 history ,可是需要服務端支持
  • 能先用簡單的,就別用複雜的,要考慮成本和收益

🎻4、結束語

對於 hashhistory 來說,要清楚二者的區別以及二者各自的使用場景,還有各自的使用特色和優缺點。以上文章只是對前端路由原理的淺談,但願對你們有幫助~

另下方第三個彩蛋放了一篇關於實現 vue-router 的文章,學有餘力的小夥伴有須要自取o!

🐣彩蛋 One More Thing

🏷️參考資料

jarvis👉在SPA項目的路由中,注意hash與history的區別

vue-router官方文檔👉vue-router的兩種模式

值得一看👉從使用到本身實現簡單Vue Router看這個就好了

🏷️番外篇

  • 關注公衆號星期一研究室,第一時間關注優質文章,更多精選專欄待你解鎖~
  • 若是這篇文章對你有用,記得留個腳印jio再走哦~
  • 以上就是本文的所有內容!咱們下期見!👋👋👋
相關文章
相關標籤/搜索