0%

[Vue] Vue Router 配置與運作

在 SPA 的架構下,頁面切換不是由後端操控,而是由前端模擬路由器來替換畫面上的內容。
而我們可以透過 Vue Router 來達成這件事。

Router 是由前端所模擬的路由器

一個使用 Vue Router 的專案會包含三個元素:

  • 進入點:main.js
  • Router 配置檔案(前端路由):router/index.js
  • 分頁內容:Vue Components (**.vue)

建置步驟

  1. 下載 Vue Router:npm install vue-router --save

  2. src 資料夾裡新建 router 資料夾:在裡面新增一個 index.js,作為放置整個路由的配置檔

  3. index.js 一開始要寫入的是官方元件:

    1
    2
    3
    // 官方元件
    import Vue from 'vue';
    import VueRouter from 'vue-router';
  4. 載入自訂元件,也就是把 components 資料夾內的 .vue 檔寫入 index.js

    1
    2
    // 自訂的分頁元件
    import Home from 'src/components/HelloWorld';
  5. 啟用 router:Vue.use(VueRouter);

  6. index.js 匯出給進入點(main.js)使用:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // 在 index.js 繼續寫
    export default new VueRouter({
    // 陣列內可放多組路徑及對應的元件
    routes:[
    {
    name: '首頁', // 元件呈現的名稱
    path: '/index', // 對應的虛擬路徑
    component: Home, // 對應的元件
    },
    ],
    });
  7. main.js 匯入 router:

    1
    2
    import router from './router';
    // 再到 new Vue 下面加上 router 這個單字
  8. App.vue,在要呈現元件的地方<router-view></router-view> 替換

  9. 當網址 /# 後面接的是 /index 時,對應的元件就會呈現在畫面上

新增路由路徑及連結

  1. 新增新的路由:基本上就是在上一段第 6 點的 router 陣列裡面新增物件
  2. 在 index.html 用 CDN 載入 BS,或是用 GUI 下載 BS 套件
  3. 在 components 資料夾下新增 pages 資料夾,專門管理分頁元件
  4. 把 HelloWorld.vue 另存新檔為 page.vue,存在 pages 裡
  5. 整理 page.vue 裡的內容,只留下 <script> 區塊(data 可留空)及空的 <template>,把 BS 的卡片元件貼在 <template> 裡面
  6. 回到 router 的 index.js,在 import Home 下面新增:
    import Page form ‘/components/pages/page’;
  7. 在 router 陣列裡新增相關資訊:
    1
    2
    3
    4
    5
    {
    name: ‘分頁’,
    path: ‘/page’,
    component: Page
    }
  8. 在 App.vue 插入 BS navbar,製作分頁導覽列,其中 a 連結的標籤改為 <router-link>,並把 href 屬性改為 to="path值",例如 to="/page";或是使用 :to="{ name: '分頁'}" 也有同樣效果

巢狀路由

剛剛在 page 分頁中的卡片,如果希望卡片不變但是裡面內容被抽換,要如何透過虛擬路由來達成呢?

  1. page.vue 另存成一個叫做 child.vue 的檔案,page.vue 本身要把 .card 內層都刪掉並改成 <router-view>(用來切換內容)
  2. child.vue 去掉 .card 外層,但要留一個沒加 className<div> 外層,另存為 child2child3
  3. child 系列的檔案要把卡片標題改一改
  4. 到 router 的 index.js,將 child 系列 import 進來,並在 page 所屬的物件中新增 children 特性,children 對應的值是一個陣列,陣列內的格式跟外層物件一樣
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    {
    name: '卡片 1', // 元件呈現的名稱
    path: '', // 這裡空白代表 /page 顯示的內容就是這個子元件
    component: child, // 對應的元件
    },
    {
    name: '卡片 2', // 元件呈現的名稱
    path: 'child2',
    component: child2, // 對應的元件
    },
    {
    name: '卡片 3', // 元件呈現的名稱
    path: 'child3',
    component: child3, // 對應的元件
    },
  5. page.vue 使用 <router-link> 切換子分頁
    1
    2
    3
    <router-link to="/page/">卡片 1</router-link>
    <router-link to="/page/child2">卡片 2</router-link>
    <router-link to="/page/child3">卡片 3</router-link>

    使用動態路由切換頁面 AJAX 結果

    在同樣的版型下,用網址後面的 id 決定帶入的內容。
    讓我們把上一段的卡片 3 改成動態路由試試看!
  6. 把上一段的 path: 'child3' 改成 path: 'child/:id'id 是一個可自定義名稱的參數,這時 :id 就成為動態路由。
  7. 到卡片 3 的元件檔案(child3.vue),在 export default 的大括號內增加一個 created(),這個方法會在元件生成時執行。
  8. 存取 API 中固定的一筆資料(以 randomuser 為例):
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    const id = this.$route.params.id;
    // route 已被掛載到 Vue 上,所以可以用 $ 呼叫
    // params 是 router 的方法,可以讀取 router 裡的參數
    // id 是我們自訂的參數

    // AJAX
    // get() 中的網址參考 reandomuser 文件中的 Seeds 一節
    // ?seed=${網址參數},且 API 網址整串要用反引號包住
    this.$http.get(`https://randomuser.me/api/?seed=${id}`).then((response) => {
    console.log(response);
    });
  9. 在網址列隨意打幾個英文字,就能從 API 中抓取到特定資料。正式開發時,id 是由後端定義的,新增產品資料後會自動產生這個產品的 id ,前端要做的只是抓到這個 id ,並把資料顯示出來。

命名路由,同一個路徑載入兩個元件

為卡片多做一個導覽列。

  1. App.vue.container 上方新增一個 <router-view> 並且設定 name 屬性,例如 name="menu"
  2. page.vue 另存新檔為 menu.vuepage.vue 只留 .card 其餘的 <router-link> 刪掉,menu.vue 只留 <router-link> 其餘刪掉。
  3. 使用 BS nav 美化 menu,把 nav 程式碼貼進來,用 <router-link> 取代 nav 裡面的 <a>,記得補上 .nav-link
  4. 到 router 資料夾的 index.js 中將 menu.vue import 進來,並到下方的路由設定改寫程式碼:
    1
    2
    3
    4
    5
    // 原本使用 component 特性,改用 components 設定單一路由但多個元件
    components: {
    default: Page, // 在 router-view 沒有設定 name 時預設顯示哪個元件
    menu: Menu // 第一個 menu 是 router-view 的 name,第二個 Menu 是元件名
    },

    Vue Router 參數設定

    請搭配 Vue Router 官方文件。
    Vue Router 的 API 分為 Router 構造配置及 Router 實例,這篇只介紹常用的 Router 配置。

Router 構造配置

構造配置用於 index.js 這個檔案中,官方文件有介紹更多更詳細的方法跟屬性可用。

  • routes 物件:官方文件有列出總共有哪些特性可以調整。
  • mode 字串:決定網址的 # 是否要保留,或是做其他的設定。如果使用 history 模式,可以去除網址中的 #,但是必須配合後端使用。所以基本上還是以預設模式為主即可。
  • base 字串:根路徑設置的地方。
  • linkActiveClass 字串:當某個路徑被啟用時會被加上特定的啟用 class,在這個特性裡可以設定路徑啟用的 className。
  • linkExactActiveClass 字串:跟上一個差不多。

自定義切換路由方法

有些行為必須在 AJAX 結束後才去切換畫面,此時 router-link 就不一定適用。

舉例來說,當我們在電商網站買完東西、結帳送出後,需要進行一些 AJAX 的行為,得到資料後使用一些方法,使網頁切換。

此時,我們應該運用元件 methods + Vue Router 的實例方法,來切換畫面。

在官方文件的 API / Router 實例方法中,有許多我們能運用的方法,其中較常用的有:

  • router.push():括號裡放入'路徑'
  • router.back():回到上一頁,括號裡不需放參數。
  • router.forward():前進下一頁,括號裡不需放參數。
  • router.go():括號裡放入數值,代表前進(正數)或後退(負數)的頁數。
  • router.replace():括號裡放入'路徑',透過這個方法前往指定路徑,將不會記錄在瀏覽器。

應用方式

  1. 在元件寫一個 <a>,並綁定一個自訂的事件,透過這個事件來更新路徑。
    1
    <a href="#" @click.prevent="updatePath">切換到指定頁面</a>
  2. 在元件裡新增 methods,使用 router.push() 方法。
    1
    2
    3
    4
    5
    methods: {
    updatePath() {
    this.$router.push('/page/child2');
    }
    }