前端框架路由實現的Hash和History兩種模式的區別

Hal的Gold發表於2019-10-18

前言

  • 之前面試的時候就有準備過前端框架中兩種路由實現方式及區別,但是當時沒專門下功夫去深入瞭解,就在網上搜了下別人總結的臨時抱了下佛腳。但是事實證明,出來混,總是要還的,在後來的面試中又遇到了,而且這次問得更加深入,僅僅靠死記硬背來的知識總是遺忘得很快,網上別人總結的東西終歸還是別人的,鑑於網上別人總結的內容有點雜亂無章,還是決定自己在此總結記錄一番,以加深印象。

一、何為前端路由

  • 路由的概念來自於伺服器端,在SPA(單頁應用)中,路由描述的是URL到函式的對映關係,即在瀏覽器中輸入一個URL,相應的控制器會對提交的請求進行解析,然後進行路由匹配,找到對應的模組和函式進行執行。

二、如何實現

  • 實現的兩個核心問題是如何檢測路由變化和如何改變URL而不重新整理頁面,通常有兩種實現模式,一種是Hash模式,一種是History模式。

三、Hash模式

  • 早期的前端路由的實現就是基於location.hash來實現的,location.hash的值就是URL中#後面的內容 其實現原理就是監聽#後面的內容來發起Ajax請求來進行區域性更新,而不需要重新整理整個頁面。
  • 使用hashchange事件來監聽 URL 的變化,以下這幾種情況改變 URL 都會觸發 hashchange 事件:瀏覽器前進後退改變 URL、<a>標籤改變 URL、window.location改變URL。

優缺點

  • 相容低版本瀏覽器,Angular1.x和Vue預設使用的就是hash路由
  • 只有#符號之前的內容才會包含在請求中被髮送到後端,也就是說就算後端沒有對路由全覆蓋,但是不會返回404錯誤
  • hash值的改變,都會在瀏覽器的訪問歷史中增加一個記錄,所以可以通過瀏覽器的回退、前進按鈕控制hash的切換
  • 會覆蓋錨點定位元素的功能
  • 不太美觀,#後面傳輸的資料複雜的話會出現問題

四、History模式

  • history 提供了 pushStatereplaceState 兩個方法來記錄路由狀態,這兩個方法改變 URL 不會引起頁面重新整理
  • history 提供類似 hashchange 事件的 popstate 事件,但 popstate 事件有些不同:通過瀏覽器前進後退改變 URL 時會觸發 popstate 事件,通過pushState/replaceState或<a>標籤改變 URL 不會觸發 popstate 事件。好在我們可以攔截 pushState/replaceState的呼叫和<a>標籤的點選事件來檢測 URL 變化,所以監聽 URL 變化可以實現,只是沒有 hashchange 那麼方便。
  • pushState(state, title, url)replaceState(state, title, url)都可以接受三個相同的引數:
  • state:需要儲存的資料,這個資料在觸發popstate事件時,可以在event.state裡獲取
  • title:標題,基本沒用,一般傳 null
  • url:設定新的歷史記錄的 url,新的 url 與當前 url 的 origin 必須是一樣的,否則會拋錯,url可以是絕對路徑,也可以是相對路徑。

優缺點

  • 使用簡單,比較美觀
  • pushState()設定新的URL可以是任意與當前URL同源的URL,而hash只能改變#後面的內容,因此只能設定與當前URL同文件的URL
  • pushState()設定的URL與當前URL一模一樣時也會被新增到歷史記錄棧中,而hash#後面的內容必須被修改才會被新增到新的記錄棧中
  • pushState()可以通過stateObject引數新增任意型別的資料到記錄中,而hash只能新增短字串
  • pushState()可額外設定title屬性供後續使用
  • 前端的URL必須和向傳送請求後端URL保持一致,否則會報404錯誤
  • 由於History API的緣故,低版本瀏覽器有相容行問題

參考

相關文章