在 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.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()
:括號裡放入'路徑'
,透過這個方法前往指定路徑,將不會記錄在瀏覽器。
應用方式
- 在元件寫一個
<a>
,並綁定一個自訂的事件,透過這個事件來更新路徑。1
<a href="#" @click.prevent="updatePath">切換到指定頁面</a>
- 在元件裡新增
methods
,使用router.push()
方法。1
2
3
4
5methods: {
updatePath() {
this.$router.push('/page/child2');
}
}