完全搞懂路由跳轉:location 和 history 接口

在單頁應用中,一般由前端來配置路由,根據不一樣的 url 顯示不一樣的內容。想要知道這是如何作到的,首先得了解瀏覽器提供的兩大 API:前端

  1. window.locationvue

    • location.href
    • location.hash
    • location.search
    • location.pathname
  2. window.historyvue-router

    • history.pushState()
    • history.replaceState()
    • history.go()
    • history.back()
    • history.forward()

window.location

咱們先了解 location 對象,location 有不少的屬性。咱們能夠經過改變其屬性值修改頁面的 url。咱們在單頁應用中須要作到的是改變 url 不刷新頁面,location 接口提供如下兩種方式能夠作到:後端

  1. location.href 賦值時只改變 url 的 hash
    圖片描述
  2. 直接賦值 location.hash
    圖片描述

而上面的列出其他兩個屬性 location.search 會直接刷新頁面,這個就不解釋了。但 location.pathname 照道理來講只改變 hash 應該是能夠的,但實際上瀏覽器會編碼這個屬性值,因此沒法直接賦帶 # 號的值。瀏覽器

window.history

history 接口是 HTML5 新增的,它有五個方法能夠改變 url 而不刷新頁面。編碼

  1. history.pushState()
    圖片描述
  2. history.replaceState()
    圖片描述
  3. history.go()
    圖片描述

上面只演示了三個方法,由於 history.back() 等價於 history.go(-1)history.forward() 則等價於 history.go(1),這三個接口等同於瀏覽器界面的前進後退。url

如何監聽 url 的變化

如今咱們已經知道如何不刷新頁面改變頁面的 url。雖然頁面沒刷新,但咱們要改變頁面顯示的內容。這就須要 js 監聽 url 的變化從而達到咱們的目的。spa

咱們有兩個事件能夠監聽 url 的改變:code

hashchange

hashchange 事件能監聽 url hash 的改變。router

先要加上事件監聽的代碼:

window.addEventListener('hashchange', function(e) {
  console.log(e)
})

而後就能夠在頁面的 console 裏愉快的實驗了:

圖片描述

從上圖中咱們能夠知道無論是經過 location 接口直接改變 hash,仍是經過 history 接口前進後退(只是 hash 改變的狀況下),咱們均可以監聽到 url hash 的改變。但這個事件也只能監聽 url hash 的變化。因此咱們須要一個更強大的事件:popstate

popstate

popstate 事件能監聽除 history.pushState()history.replaceState() 外 url 的變化。

先加上事件監聽的代碼:

window.addEventListener('popstate', function(e) {
  console.log(e)
})

而後又能夠在頁面的 console 裏愉快的實驗了:

圖片描述

其實不止 history.pushState()history.replaceState() 對 url 的改變不會觸發 popstate 事件,當這兩個方法只改變 url hash 時也不會觸發 hashchange 事件。

hash 模式和 history 模式

咱們都知道單頁應用的路由有兩種模式:hash 和 history。若是咱們在 hash 模式時不使用 history.pushState()history.replaceState() 方法,咱們就只須要在 hashchange 事件回調裏編寫 url 改變時的邏輯就好了。而 history 模式下,咱們不只要在 popstate 事件回調裏處理 url 的變化,還須要分別在 history.pushState()history.replaceState() 方法裏處理 url 的變化。並且 history 模式還須要後端的配合,否則用戶刷新頁面就只有 404 能夠看了?

因此 hash 模式下咱們的工做實際上是更簡單的,但爲何如今都推薦用 history 模式呢?總不是 hash 模式下的 url 太醜了,畢竟這是個看臉的世界?

不過 vue-router 在瀏覽器支持 pushState() 時就算是 hash 模式下也是用 history.pushState() 來改變 url,不知道有沒什麼深意?還有待研究...

相關文章
相關標籤/搜索