vue-router的hash模式和history模式詳解

參考來源:
1、vue-router是什麼

​ vue-router就是WebApp的連接路徑管理系統。vue的單頁面應用是基於路由和組件的,路由用於設定訪問路徑,並將路徑和組件映射起來。傳統的頁面應用,是用一些超連接來實現頁面切換和跳轉的。在vue-router單頁面應用中,則是路徑之間的切換,也就是組件的切換。路由模塊的本質 就是創建起url和頁面之間的映射關係javascript

問題:爲何不用a標籤html

2、vue-router實現原理
1.vue-router 默認 hash 模式

​ 使用 URL 的 hash 來模擬一個完整的 URL,因而當 URL 改變時,頁面不會從新加載。 hash(#)是URL 的錨點,表明的是網頁中的一個位置,單單改變#後的部分,瀏覽器只會滾動到相應位置,不會從新加載網頁,也就是說hash 出如今 URL 中,但不會被包含在 http 請求中,對後端徹底沒有影響,所以改變 hash 不會從新加載頁面;同時每一次改變#後的部分,都會在瀏覽器的訪問歷史中增長一個記錄,使用」後退」按鈕,就能夠回到上一個位置;因此說Hash模式經過錨點值的改變,根據不一樣的值,渲染指定DOM位置的不一樣數據。前端

問題:是怎麼監聽hash變化的——hashchange()vue

如何簡單實現:html5

  1. Class關鍵字初始化一個路由.
class Routers {
  constructor() {
    // 以鍵值對的形式儲存路由
    this.routes = {};
    // 當前路由的URL
    this.currentUrl = '';
  }
}
複製代碼
  1. 實現路由hash儲存與執行。在初始化完畢後咱們須要思考兩個問題:java

    • 將路由的hash以及對應的callback函數儲存
    • 觸發路由hash變化後,執行對應的callback函數
    class Routers {
      constructor() {
        this.routes = {};
        this.currentUrl = '';
      }
      // 將path路徑與對應的callback函數儲存
      route(path, callback) {
        this.routes[path] = callback || function() {};
      }
      // 刷新
      refresh() {
        // 獲取當前URL中的hash路徑
        this.currentUrl = location.hash.slice(1) || '/';
        // 執行當前hash路徑的callback函數
        this.routes[this.currentUrl]();
      }
    }
    複製代碼
  2. 監聽對應事件,咱們只須要在實例化Class的時候監聽上面的事件便可.面試

class Routers {
  constructor() {
    this.routes = {};
    this.currentUrl = '';
    this.refresh = this.refresh.bind(this);
    window.addEventListener('load', this.refresh, false);
    window.addEventListener('hashchange', this.refresh, false);
  }

  route(path, callback) {
    this.routes[path] = callback || function() {};
  }

  refresh() {
    this.currentUrl = location.hash.slice(1) || '/';
    this.routes[this.currentUrl]();
  }
}

複製代碼

完整示例:hash router的初步實現vue-router

  1. 此外還要實現回退功能等,hash router完整代碼參考
2.vue-router 可選擇 history模式

​ 因爲hash模式會在url中自帶#,若是不想要很醜的 hash,咱們能夠用路由的 history 模式,只須要在配置路由規則時,加入"mode: 'history'".後端

//main.js文件中
const router = new VueRouter({
  mode: 'history',
  routes: [...]
})
複製代碼

​ 這種模式充分利用了html5 history interface 中新增的 pushState() 和 replaceState() 方法。這兩個方法應用於瀏覽器記錄棧,在當前已有的 back、forward、go 基礎之上,它們提供了對歷史記錄修改的功能。只是當它們執行修改時,雖然改變了當前的 URL ,但瀏覽器不會當即向後端發送請求。不過這種模式要玩好,還須要後臺配置支持。由於咱們的應用是個單頁客戶端應用,若是後臺沒有正確的配置,當用戶在瀏覽器直接訪問 outsite.com/user/id 就會返回 404,這就很差看了。因此呢,你要在服務端增長一個覆蓋全部狀況的候選資源:若是 URL 匹配不到任何靜態資源,則應該返回同一個 index.html 頁面,這個頁面就是你 app 依賴的頁面。瀏覽器

export const routes = [ 
  {path: "/", name: "homeLink", component:Home}
  {path: "/register", name: "registerLink", component: Register},
  {path: "/login", name: "loginLink", component: Login},
  {path: "*", redirect: "/"}]
複製代碼
2.1.history API介紹:

img

其中經常使用的只有幾種:

window.history.back();       // 後退
window.history.forward();    // 前進
window.history.go(-3);       // 後退三個頁面
複製代碼

history.pushState用於在瀏覽歷史中添加歷史記錄,可是並不觸發跳轉,此方法接受三個參數,依次爲:

state:一個與指定網址相關的狀態對象,popstate事件觸發時,該對象會傳入回調函數。若是不須要這個對象,此處能夠填null。
title:新頁面的標題,可是全部瀏覽器目前都忽略這個值,所以這裏能夠填null。
url:新的網址,必須與當前頁面處在同一個域。瀏覽器的地址欄將顯示這個網址。
複製代碼

history.replaceState方法的參數與pushState方法如出一轍,區別是它修改瀏覽歷史中當前紀錄,而非添加記錄,一樣不觸發跳轉。

popstate事件,每當同一個文檔的瀏覽歷史(即history對象)出現變化時,就會觸發popstate事件。

2.2.新標準下路由的實現:
class Routers {
  constructor() {
    this.routes = {};
    this._bindPopState();
  }
  init(path) {
    history.replaceState({path: path}, null, path);
    this.routes[path] && this.routes[path]();
  }

  route(path, callback) {
    this.routes[path] = callback || function() {};
  }

  go(path) {
    history.pushState({path: path}, null, path);
    this.routes[path] && this.routes[path]();
  }
  _bindPopState() {
    window.addEventListener('popstate', e => {
      const path = e.state && e.state.path;
      this.routes[path] && this.routes[path]();
    });
  }
}

window.Router = new Routers();
Router.init(location.pathname);
const content = document.querySelector('body');
const ul = document.querySelector('ul');
function changeBgColor(color) {
  content.style.backgroundColor = color;
}

Router.route('/', function() {
  changeBgColor('yellow');
});
Router.route('/blue', function() {
  changeBgColor('blue');
});
Router.route('/green', function() {
  changeBgColor('green');
});

ul.addEventListener('click', e => {
  if (e.target.tagName === 'A') {
    e.preventDefault();
    Router.go(e.target.getAttribute('href'));
  }
});

複製代碼
3.使用路由模塊來實現頁面跳轉的方式
  • 方式1:直接修改地址欄
  • 方式2:this.$router.push(‘路由地址’)
  • 方式3:<router-link to="路由地址"></router-link>
相關文章
相關標籤/搜索