菜蟲學習筆記:Vue Router 配置

在完成基本的webpack設定後,接著要安裝的是Vue Router
Vue Router是vue的套件,為前端模擬路由,達成切換網址時也能切換到相對組件的效果。
Introduction | Vue Router

Vue Router 安裝

NPM下載

1
npm install vue-router --save

Vue Router 設置

1. Router配置檔案(前端路由)

→決定由哪個網址讀取元件
建立資料夾及檔案:src/router/index.js
index.js配置檔案中須包含以下程式碼以安裝路由功能:

1
2
3
4
5
6
7
8
// 此為Vue Cli 2.x
import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)
export default new VueRouter({

});

2. 將檔案匯出至main.js

接著,需要將index.js設定的資料,匯出給entrymain.js使用
將檔案import進入main.js寫法為:

1
2
import router from './router'; // 將步驟1的index.js匯入至main.js
router // 將配置檔router加入new vue之下

main.js 結果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
import Vue from 'vue';
import App from './App';
import router from './router'; // 將步驟1的index.js匯入至main.js

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
el: '#app',
components: { App },
template: '<App/>',
router, // 將配置檔router加入new vue之下
})
設定後網址會增加#字號,但畫面還不會有任何改變。

3. 定義 Router 路徑

在router中定義路徑,至index.js內增加routes

1
2
3
4
5
6
7
8
9
10
11
import Home from '../components/HelloWorld'  // 先將將檔案引入,再做component的對應

export default new VueRouter({
routes: [
{
name: '首頁', // 元件呈現的名稱
path: '/', // 對應的虛擬路徑
component: Home, // 對應的元件
}
]
});

此處Vue Cli 3寫法會有不同,寫法為:

1
2
3
4
5
6
7
8
const routes: [
{
name: '首頁', // 元件呈現的名稱
path: '/', // 對應的虛擬路徑
component: () => import('../components/HelloWorld.vue') // Cli3直接在此引入即可
}
];
export default router

完成基本配置後,由於使用了 Vue.use( VueRouter ),會在 Vue 中增加 這兩個組件。

打開App.vue將router要呈現的頁面放在元件上,<router-view></router-view>為呈現元件的地方。

1
2
3
4
5
<template>
<div id="app">
<router-view/>
</div>
</template>

<router-view/>

<router-view> 渲染的組件還可以內嵌自己的<router-view>,根據路徑去渲染组件。
其他屬性(非 router-view 使用的屬性)都會直接傳給渲染的組件,大部份每個路由的數據都是包含在路由參數中。

1
2
3
4
// 基本view,自動預設name屬性為default
<router-view />
// 具名view,name屬性會負責渲染相對設定組件
<router-view name="name" />

切換路徑的連結,實際會渲染出一個a連結,如下:

1
<router-link to="path">連結</router-link>

5. 新增Router路徑及連結

新增路徑

1
2
3
4
5
6
7
8
9
10
11
12
13
14
export default new VueRouter({
routes: [
{
name: '首頁',
path: '/index',
component: Home,
},
{
name: '新元件名稱', // 元件呈現的名稱
path: '/新路徑', // 對應的虛擬路徑
component: 新元件, // 對應的元件
},
],
});

新增連結

Vue Router寫法(透過path):

1
2
3
<li class="nav-item active">
<router-link class="nav-link" to="/index">Home</router-link>
</li>

※ 將a更換為router-link,href=”#”更換為to=”/“ (to路徑為index.js內設定的path)

Vue Router寫法(透過name):

1
2
3
<li class="nav-item active">
<router-link class="nav-link" :to="{ name:'首頁' }">Home</router-link>
</li>

※ 將a更換為router-link,href=”#”更換為動態顯示:to=”{ name:’首頁’ }”

6. 製作巢狀路由頁面

1.在新增子分頁的分頁上,加入<router-view></router-view>

1
2
3
4
5
6
7
<template>
<div id="app">
<div class="card" style="width: 18rem;">
<router-view></router-view> // router-view會協助切換子分頁的內容
</div>
</div>
</template>

2.在Router的配置檔上加入子分頁

將元件載入index.js

1
2
3
import Child from '../components/pages/child';
import Child2 from '../components/pages/child2';
import Child3 from '../components/pages/child3';

使用children:[]加入要製作子分頁的元件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
name: '分頁',  
path: '/page',
component: Page,
children: [
{
name: '卡片1', // 元件呈現的名稱
path: '', // 路徑移除,表示會直接在page之下載入元件
component: Child, // 對應的元件
},
{
name: '卡片2', // 元件呈現的名稱
path: 'child2', // 對應的虛擬路徑
component: Child2, // 對應的元件
},
{
name: '卡片3',
path: 'child3',
component: Child3,
},
],

3.切換子分頁

使用<router-link></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>

增加後畫面如下:

1
2
3
4
5
6
7
8
9
10
<template>
<div id="app">
<div class="card" style="width: 18rem;">
<router-view></router-view> // router-view會協助切換子分頁的內容
<router-link to="/page/">卡片1</router-link>
<router-link to="/page/child2">卡片2</router-link>
<router-link to="/page/child3">卡片3</router-link>
</div>
</div>
</template>

動態路由切換頁面 & ajax切換

調整動態路由路徑

1.至index.js下調整動態路由路徑,可將網址調整為動態路由(非固定分頁名稱)

1
2
3
4
5
{
name: '卡片3', // 元件呈現的名稱
path: 'child/:id', // id=動態路由
component: Child3, // 對應的元件
},

2.至需調整為動態路由的頁面中新增

1
2
3
created() {
this.$route.params.id; // 存取動態路由的方式
}

created()意思為:從router中讀取參數使用,讀取的項目為id(自定義)

3.使用axios套件取得ajax遠端資料 (axios套件安裝方式參考:)

1
2
3
this.$http.get('https://randomuser.me/api/').then((response) => {
console.log(response.data);
}

axios取得ajax資料使用方式為:

4.使用動態路由重複存取相同資料
這裡使用 Randomuser User 可用API測試串接資料

1
2
3
4
5
const id = this.$route.params.id;  // 將id讀取下來後,從router中讀取參數使用
this.$http.get(`https://randomuser.me/api/?seed=${id}`).then((response) => {
// ${id}動態讀取id資料
console.log(response);
});


同個畫面執行兩個以上router-view

Ex:

說明:點選page.vue後,會同時執行2個<router-view>(page.vue、menu.vue)

1.在App.vue新增

1
2
3
4
<router-view name="menu"></router-view> <!-- 新加入的選單,載入menu -->
<div class="container">
<router-view></router-view> <!-- 沒使用name的router-view為預設,載入page -->
</div>
  • 有新增name的router-view會連接到該內容
  • 若無使用name的router-view為預設值,此處會載入page.vue

2.至index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
// name: '分頁', // 元件呈現的名稱 // 因為要讓連結直接連到下方children中的卡片1,故此處的name需註解掉,才不會造成重複載入
path: '/page', // 對應的虛擬路徑
// component: Page, // 對應的元件
components: {
default: Page, //載入預設沒有命名的router-view
menu: Menu, //此處為對應有自定義名稱的router-view
},
children: [
{
name: '卡片1', // 元件呈現的名稱
path: '', // 路徑移除,表示會直接在page之下載入元件
component: Child, // 對應的元件
},
{
name: '卡片2', // 元件呈現的名稱
path: 'child2', // 對應的虛擬路徑
component: Child2, // 對應的元件
},
{
name: '卡片3', // 元件呈現的名稱
path: 'child3', // id=動態路由
component: Child3, // 對應的元件
},
],
}
  • 新增一個components物件,default為載入預設沒有命名的router-view,menu為對應App.vue中有自定義名稱的router-view
    1
    2
    3
    4
    components: {
    default: Page, // 載入預設沒有命名的router-view
    menu: Menu, // 此處為對應有自定義名稱的router-view
    },
  • 將原先component註解掉,此處執行替換為components物件
  • 原先的name: '分頁',在這邊也要註解掉,因為要讓default: Page直接連結到下方children中的卡片1,才不會造成重複載入

實際切換路由方法

router.push

除了使用<router-link>創建a連結來定義連結,還可以使用router的實例方法,透過編寫代碼來實現。

Declarative Programmatic
<router-link :to="..."> router.push(...)

文件使用方法:

1
2
3
4
5
6
7
8
9
10
11
// 字符串
router.push('home')

// 對象
router.push({ path: 'home' })

// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})

// 帶查詢參數,變成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})

※ 如果提供了path,params會被忽略,上述例子中的 query 並不屬於這種情況。取而代之的是下面例子的做法,需要提供路由的name或完整帶有參數的path:

1
2
3
4
5
const userId = '123'
router.push({ name: 'user', params: { userId }}) // -> /user/123
router.push({ path: `/user/${userId}` }) // -> /user/123
// 此處params不生效
router.push({ path: '/user', params: { userId }}) // -> /user

html內添加:

1
<a href="#" class="nav-link" @click.prevent="updatePath">切換GO</a>

js內添加:

1
2
3
4
5
methods: {
updatePath() {
this.$router.push('/page/child2');
},
}

router.replace

router.push很像,不同的是,它不會增加history的記錄,只會替換掉目前的history記錄。

Declarative Programmatic
<router-link :to="..." replace> router.replace(...)

router.go / router.forward

這個方法的參數是一個整數,在history記錄中向前或向後多少步,類似 window.history.go(n)
文件使用方法:

1
2
3
4
5
6
7
8
9
10
11
12
// 在瀏覽器記錄中前進一步,與history.forward()相同
router.go(1)

// 後退一步記錄,與history.back()相同
router.go(-1)

// 前進3步記錄
router.go(3)

// 如果history記錄不夠用,就只能默默的失敗啦
router.go(-100)
router.go(100)

html內添加:

1
<a href="#" class="nav-link" @click.prevent="beforePath">回到前頁</a>

js內添加:

1
2
3
4
methods: {
beforePath() {
this.$router.back();
}