天天看點

怎樣了解Vue中的路由

1. 路由

  • 傳統的路由指的是:當使用者通路一個

    url

    時,對應的伺服器會接收這個請求,然後解析url中的路徑,進而執行對應的處理邏輯。這樣就完成了一次路由分發。
  • 而前端路由是不涉及伺服器的,是前端利用

    hash

    或者

    HTML5

    history API

    來實作的,一般用于不同内容的展示和切換。

目前

Vue

推薦單頁面應用

SPA

開發模式,大型單頁應用最顯著特點之一就是采用前端路由系統,通過改變

URL

,在不重新請求頁面的情況下,更新頁面視圖。

Vue

中的路由解決方案為

vue-router

它提供兩種不同方式的路由方式:

Hash

History

,在

vue-router

中是使用了外觀模式将幾種不同的路由方式提供了一個一緻的高層接口,讓我們可以更解耦的在不同路由方式中切換。

Hash

History

除了外觀上的不同之外,還有一個差別是:

Hash

方式的狀态儲存需要另行傳遞,而

HTML5 History

原生提供了自定義狀态傳遞的能力,我們可以直接利用其來傳遞資訊。

vue-router

中是通過

mode

這一參數控制路由的實作模式的:

怎樣了解Vue中的路由

2. Hash

Hash

方法是在路由中帶有一個

#

,主要原理是通過監聽

#

後的

URL

路徑辨別符的更改而觸發的浏覽器

hashchange

事件,然後通過擷取

location.hash

得到目前的路徑辨別符,再進行一些路由跳轉的操作,參見 MDN:

  • location.href

    :傳回完整的

    URL

  • location.hash

    :傳回

    URL

    的錨部分;
  • location.pathname

    :傳回

    URL

    路徑名;
  • hashchange

    事件:當

    location.hash

    發生改變時,将觸發這個事件。

比如通路一個路徑

http://sherlocked93.club/base/#/page1

,那麼上面幾個值分别為:

# http://sherlocked93.club/base/#/page1
{
  "href": "http://sherlocked93.club/base/#/page1",
  "pathname": "/base/",
  "hash": "#/page1"
}
           

看一個例子:

<html>
<head>
  <style>
    li {
      cursor: pointer;
    }
  </style>
</head>
<body>
<div id="main">
  <p>router-hash</p>
  <ul id="list">
    <li><a href="#router1" target="_blank" rel="external nofollow" >router1</a></li>
    <li><a href="#router2" target="_blank" rel="external nofollow" >router2</a></li>
    <li><a href="#router3" target="_blank" rel="external nofollow" >router3</a></li>
  </ul>
  <div id="panel"></div>
</div>

<script>
  window.onload = function () {
    window.onhashchange = function (opt) {
      console.log('hash has changed to: ', location.hash)
    }
  }
</script>
</body>
</html>
           

效果:

怎樣了解Vue中的路由

當我們點選後退時,可見路由跳轉回

router2

中。并且當我們重新整理頁面時不會報出

404

的錯誤,那是因為

hash

雖然出現在

URL

中,但不會被包括在

HTTP

請求中。它是用來指導浏覽器動作的,對伺服器端完全無用。

3. History API

HTML5

History API

為浏覽器的全局

history

對象增加的擴充方法。一般用來解決

ajax

請求無法通過回退按鈕回到請求前狀态的問題。

HTML4

原有的和

HTML5

新提出的

history

的API有:

  • history.forward()

    ; //在曆史記錄中前進一步
  • history.back()

    ; //在曆史記錄中後退一步
  • history.go(n)

    : //在曆史記錄中跳轉n步驟,n=0為重新整理本頁,n=-1為後退一頁。
  • history.pushState(data, title, url);

    //向曆史記錄中追加一條記錄
  • history.replaceState(data, title, url);

    //替換目前頁在曆史記錄中的資訊
  • history.state;

    //是一個屬性,可以得到目前頁的

    state

    資訊。
  • window.onpopstate;

    //是一個事件,在點選浏覽器後退按鈕或

    js

    調用

    forward()

    back()

    go()

    時觸發。監聽函數中可傳入一個

    event

    對象,

    event.state

    即為通過

    pushState()

    replaceState()

    方法傳入的

    data

    參數。

以一個例子實作一下:

<html>
<head>
  <style>
    li {
      cursor: pointer;
    }
  </style>
</head>
<body>
<div id="main">
  <p>vue-router</p>
  <ul id="list">
    <li>router1</li>
    <li>router2</li>
    <li>router3</li>
  </ul>
  <div id="panel"></div>
</div>

<script>
  window.onload = function () {
    window.onpopstate = function (event) {
      console.log(event)
    };

    document.querySelector('#list').addEventListener('click', function (event) {
      if(event.target.nodeName.toLowerCase()==="li") {
        var content = event.target.innerHTML;
        var _newState;
        _newState = {
          url: location.origin + '/' + content,
          title: document.title,
          state: content
        };

        window.history.pushState(_newState, '', '/' + content);
        console.log('you have change the router to: ', content);
      }
    })
  }
</script>
</body>
</html>
           

效果:

怎樣了解Vue中的路由

總而言之就是當浏覽器通路一個頁面時,目前位址的狀态資訊會被壓入曆史棧,當調用

history.pushState()

方法向曆史棧中壓入一個新的

state

後,曆史棧頂部的指針是指向新的

state

的。可以将其作用簡單了解為假裝已經修改了

url

位址并進行了跳轉 ,除非使用者點選了浏覽器的前進、回退,或是顯式調用

HTML4

中的操作曆史棧的方法,否則不會觸發全局的

popstate

事件。以上例子中點選後退可見由目前的

router2

跳轉到

router3

,控制台列印出

popstate

事件資訊。

當我們重新整理頁面的時候,會報出

404

的錯誤:

怎樣了解Vue中的路由

這也是

history

不同于

hash

的一個地方,是因為

history

模式則會将

URL

修改得就和正常向後端發起請求一樣,如果後端沒有配置對應的路由處理,則會傳回

404

錯誤。

官方推薦的解決辦法是在服務端增加一個覆寫所有情況的候選資源:如果

URL

比對不到任何靜态資源,則應該傳回同一個

index.html

頁面,這個頁面就是你

app

依賴的頁面。

參考:

https://www.cnblogs.com/dashnowords/p/9671213.html 大史不說話

https://juejin.im/post/5c52da9ee51d45221f242804 SHERlocked93