前端兩種路由實現和使用場景

在學習vue-router時,瞭解到前端路由的兩種模式,本文就前端路由,及其兩種模式的原理和使用場景,作一個整理總結。html

前端路由概述

什麼是路由

路由這個概念最早是後端出現的,簡單來講路由就是用來跟後端服務器進行交互的一種方式,經過不一樣的路徑,來請求不一樣的資源,請求不一樣的頁面是路由的其中一種功能。前端

前端路由的誕生

前端路由的出現要從 ajax 開始,有了 Ajax 後,用戶交互就不用每次都刷新頁面,體驗帶來了極大的提高。隨着技術的發展,簡單的異步已經不能知足需求,因此異步的更高級體驗出現了——SPA(單頁應用)。 SPA 的出現大大提升了 WEB 應用的交互體驗。在與用戶的交互過程當中,再也不須要從新刷新頁面,獲取數據也是經過 Ajax 異步獲取,頁面顯示變的更加流暢。 但因爲 SPA 中用戶的交互是經過 JS 改變 HTML 內容來實現的,頁面自己的 url 並無變化,這致使了兩個問題:vue

  • SPA 沒法記住用戶的操做記錄,不管是刷新、前進仍是後退,都沒法展現用戶真實的指望內容。
  • SPA 中雖然因爲業務的不一樣會有多種頁面展現形式,但只有一個 url,對 SEO 不友好,不方便搜索引擎進行收錄。

前端路由就是爲了解決上述問題而出現的。node

什麼是前端路由

簡單的說,就是在保證只有一個 HTML 頁面,且與用戶交互時不刷新和跳轉頁面的同時,爲 SPA 中的每一個視圖展現形式匹配一個特殊的 url。在刷新、前進、後退和SEO時均經過這個特殊的 url 來實現。 爲實現這一目標,咱們須要作到如下二點:ajax

  • 改變 url 且不讓瀏覽器像服務器發送請求。
  • 能夠監聽到 url 的變化

接下來要介紹的 hash 模式和 history 模式,就是實現了上面的功能。vue-router

Hash模式

原理

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

使用

//html
<ul id="menu">
  <li>
    <a href="#index">首頁</a>
  </li>
  <li>
    <a href="#news">資訊</a>
  </li>
  <li>
    <a href="#user">我的中心</a>
  </li>
</ul>
<div id="app"></div>

//js
function hashChange(e){
    let app = document.getElementById('app')
    switch (location.hash) {
      case '#index':
        app.innerHTML = '<h1>這是首頁內容</h1>'
        break
      case '#news':
        app.innerHTML = '<h1>這是新聞內容</h1>'
        break
      case '#user':
        app.innerHTML = '<h1>這是我的中心內容</h1>'
        break
      default:
        app.innerHTML = '<h1>404</h1>'
    }
}
window.onhashchange = hashChange
hashChange()
複製代碼

優勢

  • 兼容低版本瀏覽器,Angular1.x和Vue默認使用的就是hash路由
  • 只有#符號以前的內容纔會包含在請求中被髮送到後端,也就是說就算後端沒有對路由全覆蓋,可是不會返回404錯誤
  • hash值的改變,都會在瀏覽器的訪問歷史中增長一個記錄,因此能夠經過瀏覽器的回退、前進按鈕控制hash的切換 會覆蓋錨點定位元素的功能

缺點

  • 不太美觀,#後面傳輸的數據複雜的話會出現問題

History模式

原理

  • history 提供了 pushState 和 replaceState 兩個方法來記錄路由狀態,這兩個方法改變 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)均可以接受三個相同的參數。

使用

//html
<ul id="menu">
  <li>
    <a href="/index">首頁</a>
  </li>
  <li>
    <a href="/news">資訊</a>
  </li>
  <li>
    <a href="/user">我的中心</a>
  </li>
</ul>
<div id="app"></div>

//js
document.querySelector('#menu').addEventListener('click',function (e) {
  if(e.target.nodeName ==='A'){
    e.preventDefault()
    let path = e.target.getAttribute('href')  //獲取超連接的href,改成pushState跳轉,不刷新頁面
    window.history.pushState({},'',path)  //修改瀏覽器中顯示的url地址
    render(path)  //根據path,更改頁面內容
  }
})

function render(path) {
  let app = document.getElementById('app')
  switch (path) {
    case '/index':
      app.innerHTML = '<h1>這是首頁內容</h1>'
      break
    case '/news':
      app.innerHTML = '<h1>這是新聞內容</h1>'
      break
    case '/user':
      app.innerHTML = '<h1>這是我的中心內容</h1>'
      break
    default:
      app.innerHTML = '<h1>404</h1>'
  }
}
window.onpopstate = function (e) {
  render(location.pathname)
}
render('/index')
複製代碼

優勢

  • 使用簡單,比較美觀
  • pushState()設置新的URL能夠是任意與當前URL同源的URL,而hash只能改變#後面的內容,所以只能設置與當前URL同文檔的URL
  • pushState()設置的URL與當前URL如出一轍時也會被添加到歷史記錄棧中,而hash#後面的內容必須被修改纔會被添加到新的記錄棧中
  • pushState()能夠經過stateObject參數添加任意類型的數據到記錄中,而hash只能添加短字符串
  • pushState()可額外設置title屬性供後續使用

缺點

  • 前端的URL必須和向發送請求後端URL保持一致,不然會報404錯誤
  • 因爲History API的緣故,低版本瀏覽器有兼容行問題

兩種不一樣使用場景

  • 從上文可見,hash模式下url會帶有#,當你但願url更優雅時,可使用history模式。
  • 當使用history模式時,須要注意在服務端增長一個覆蓋全部狀況的候選資源:若是 URL 匹配不到任何靜態資源,則應該返回同一個 index.html 頁面,這個頁面就是你 app 依賴的頁面。
  • 當須要兼容低版本的瀏覽器時,建議使用hash模式。
  • 當須要添加任意類型數據到記錄時,可使用history模式。

參考連接:後端

相關文章
相關標籤/搜索