在 SPA 的架構下,頁面切換不是由後端操控,而是由前端模擬路由器來替換畫面上的內容。
而我們可以透過 Vue Router 來達成這件事。
Router 是由前端所模擬的路由器
一個使用 Vue Router 的專案會包含三個元素:
- 進入點:main.js
- Router 配置檔案(前端路由):router/index.js
- 分頁內容:Vue Components (**.vue)
建置步驟
下載 Vue Router:
npm install vue-router --save在
src資料夾裡新建router資料夾:在裡面新增一個index.js,作為放置整個路由的配置檔index.js一開始要寫入的是官方元件:1
2
3// 官方元件
import Vue from 'vue';
import VueRouter from 'vue-router';載入自訂元件,也就是把
components資料夾內的.vue檔寫入index.js:1
2// 自訂的分頁元件
import Home from 'src/components/HelloWorld';啟用 router:
Vue.use(VueRouter);將
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, // 對應的元件
},
],
});在
main.js匯入 router:1
2import router from './router';
// 再到 new Vue 下面加上 router 這個單字到
App.vue,在要呈現元件的地方用<router-view></router-view>替換當網址
/#後面接的是/index時,對應的元件就會呈現在畫面上
新增路由路徑及連結
- 新增新的路由:基本上就是在上一段第 6 點的 router 陣列裡面新增物件
- 在 index.html 用 CDN 載入 BS,或是用 GUI 下載 BS 套件
- 在 components 資料夾下新增 pages 資料夾,專門管理分頁元件
- 把 HelloWorld.vue 另存新檔為 page.vue,存在 pages 裡
- 整理 page.vue 裡的內容,只留下
<script>區塊(data可留空)及空的<template>,把 BS 的卡片元件貼在<template>裡面 - 回到 router 的 index.js,在
import Home下面新增:import Page form ‘/components/pages/page’; - 在 router 陣列裡新增相關資訊:
1
2
3
4
5{
name: ‘分頁’,
path: ‘/page’,
component: Page
} - 在 App.vue 插入 BS navbar,製作分頁導覽列,其中 a 連結的標籤改為
<router-link>,並把href屬性改為to="path值",例如to="/page";或是使用:to="{ name: '分頁'}"也有同樣效果
巢狀路由
剛剛在 page 分頁中的卡片,如果希望卡片不變但是裡面內容被抽換,要如何透過虛擬路由來達成呢?
- 將
page.vue另存成一個叫做child.vue的檔案,page.vue本身要把.card內層都刪掉並改成<router-view>(用來切換內容) child.vue去掉.card外層,但要留一個沒加className的<div>外層,另存為child2、child3- child 系列的檔案要把卡片標題改一改
- 到 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, // 對應的元件
}, - 在
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 改成動態路由試試看! - 把上一段的
path: 'child3'改成path: 'child/:id',id是一個可自定義名稱的參數,這時:id就成為動態路由。 - 到卡片 3 的元件檔案(
child3.vue),在export default的大括號內增加一個created(),這個方法會在元件生成時執行。 - 存取 API 中固定的一筆資料(以 randomuser 為例):
1
2
3
4
5
6
7
8
9
10
11const 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);
}); - 在網址列隨意打幾個英文字,就能從 API 中抓取到特定資料。正式開發時,id 是由後端定義的,新增產品資料後會自動產生這個產品的 id ,前端要做的只是抓到這個 id ,並把資料顯示出來。
命名路由,同一個路徑載入兩個元件
為卡片多做一個導覽列。
- 在
App.vue的.container上方新增一個<router-view>並且設定name屬性,例如name="menu"。 page.vue另存新檔為menu.vue,page.vue只留.card其餘的<router-link>刪掉,menu.vue只留<router-link>其餘刪掉。- 使用 BS nav 美化 menu,把 nav 程式碼貼進來,用
<router-link>取代 nav 裡面的<a>,記得補上.nav-link。 - 到 router 資料夾的
index.js中將menu.vueimport進來,並到下方的路由設定改寫程式碼: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():括號裡放入'路徑',透過這個方法前往指定路徑,將不會記錄在瀏覽器。
應用方式
- 在元件寫一個
<a>,並綁定一個自訂的事件,透過這個事件來更新路徑。1
<a href="#" @click.prevent="updatePath">切換到指定頁面</a>
- 在元件裡新增
methods,使用router.push()方法。1
2
3
4
5methods: {
updatePath() {
this.$router.push('/page/child2');
}
}