---
tags: VUE 3 課程筆記
---
# VUE 3 課程筆記 (八) Vue Router
## what is Vue Router
### 後端路由 router 主要是在做任務分配的工作:
![](https://i.imgur.com/Zvjt32D.png)
Client 跟 Server 要資料然後由 router 分配再讓 controller 告訴 model 需要什麼資料,再把資料跟 view 結合後回傳給 server 再提供給 Client
### 前端路由:
由前端所模擬的路由所以網址中間會多一個 /#/
會建立一個虛擬的路徑,然後依照路徑上的需求調用要用到的元件
### Vue Router 開發流程:
1. 引入 Vue Router 環境
2. 定義元件
3. 定義路由表
4. 加入對應連結
## Vue CLI + Vue Router
路由表會放在 ```router/index.js``` 這隻檔案裡面
1. 引入 Vue Router 環境(基本上 Vue CLI 已經會把所有基本設定都建立好了)
```javascript=
import { createRouter, createWebHashHistory } from 'vue-router'
```
這邊就是路由表的設定區域,設定內容會有 path 、 name 、 component 三個部分, path 是設定路徑, name 是頁面名稱(方便動態載入), component 則是 import 頁面檔案的路徑
```javascript=
const routes = [
{
path: '/',
name: 'home',
component: () => import('../views/HomeView.vue')
},
{
path: '/about',
name: 'about',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
},
{
path: '/newpage',
name: '新增頁面',
component: () => import('../views/NewPage.vue')
}
]
```
這邊是基本預設,history 的部分是讓這個 Vue Router 是用一個 Hash 的方式(/#/),下面那個 routes 就是對應上面路由表的內容
最後再 export 這個檔案給 main.js 去 import
```javascript=
const router = createRouter({
history: createWebHashHistory(),
routes
})
export default router
```
3. 定義元件
這邊會先把頁面 & 元件都先準備好檔案(不一定要先都寫完,有檔案就好)
5. 定義路由表
開始填寫 ```index.js``` 裡面 routes 區域的 path、name、component
7. 加入對應連結
在 ```App.vue```這個基礎頁面的檔案當中加入我們所需要加入的 ```<router-link to="path"></router-link>```以及顯示 頁面/元件 的```<router-view></router-view>```
## 巢狀路由
巢狀路由就是在原本的路由表的頁面裡面再加入下一層的路由,新增方法跟第一層路由大同小異
```javascript=
const routes = [
{
// 頁面一
path: '/',
name: 'home',
component: () => import('../檔案路徑'),
// 新增一個 children 陣列來放置下一層的路由
children: [
{
path: 'pathName',
component: () => import('../檔案路徑')
}
]
},
{
// 頁面二
},
{
// 頁面三
}
]
```
完成後一樣在頁面裏面加入```<router-link to="page/path"></router-link>```以及```<router-view></router-view>```
這邊要注意,```<router-link to="">```的路徑要寫完整,是包含兩層(/page/子page)的哦
## 一個元件插入多個視圖-具名視圖
可以在同一個元件裏面插入多個 router-view 然後可以增加 name 屬性
```htmlembedded=
<router-view name="name1"></router-view>
<router-view name="name2"></router-view>
```
載入路由表的時候會改變一個地方:
```javascript=
{
path:'元件路由路徑',
component: () => import('元件檔案路徑'),
children: [
{
path:'元件路由路徑',
components: {
name1: () => import('元件檔案路徑'),
name2: () => import('元件檔案路徑')
}
},
{
path:'元件路由路徑',
components: {
name3: () => import('元件檔案路徑'),
name4: () => import('元件檔案路徑')
}
}
]
}
```
這邊 components 裡面的物件屬性名稱會使用 router-view 上面的屬性名稱做對應。
最後再把對應連結 ```router-link```加上去,完成!
## 透過參數決定路由內容-動態路由
因為產品或相關資料會有超多,把資料一個一個建立到路由表上面根本就是神經病工作,所以可以使用動態路由,運用 axios + router 去判斷要接收的資訊是哪個產品,直接動態建立路由表。
### 關鍵點:把路由表變成動態的
```javascript=
{
path:'元件路由路徑/:id',
component:() => import('元件檔案路徑')
}
```
這邊 :id 是一個動態對應要顯示資料的 id 的東西, 約莫就是一個在 router 裡面的 ":"(v-bind) !?
### 元件裏面抓 id (這邊用一個 randomuser 做示範)
```javascript=
import axios from 'axios';
export default {
created () {
// 把 id 抓出來
const seed = this.$route.params.id;
// 這邊會因為每個 api 放 id 的位置不同
// 在 this.$route 後面要接的位置會不同
// 要記得看一下 id 在資料哪裡哦~
axios.get(`遠端api網址/?seed=${seed}`)
.then(
(res) => {
要存資料的動作
}
)
}
}
```
## 動態路由搭配 Props
運用 props 直接從路由裡面撈 id
路由表裡面的東西會長成這樣
```javascript=
{
path: '元件路由路徑/:id',
component: () => import('元件檔案路徑'),
props: (route) => {
return {
// 在這邊觸發 route 再用 props 結合到元件上
id: route.params.id,
}
}
}
```
```htmlembedded=
<script>
import axios from 'axios';
export default {
// 加上 props 的 功能帶上 id
props: ['id'],
created() {
const seed = this.id
axios.get(`遠端 api 網址/?seed=${seed}`)
.then(
(res) => {
console.log(res)
}
)
},
}
</script>
```
## 路由方法介紹
$route 是可以取得路由的屬性
$router 是可以使用 router 的方法
下面有幾種好像比較常會用到的路由方法:
```javascript=
eport default {
methods: {
getRoute () {
// 可以看到所有的 $router 方法
console.log(this.$router)
},
// 包含歷史紀錄
push () {
// 方法一
this.$router.push('加入路由路徑')
// 方法二
this.$router.push({
name: 'router-link 的 name'
})
},
// 不會產生歷史紀錄
replace () {
// 方法一
this.$router.replace('加入路由路徑')
// 方法二
this.$router.replace({
name: 'router-link 的 name'
})
},
// 前進到歷史紀錄的前或後幾頁
go () {
this.$router.go(+/- 頁數)
}
}
}
```
## 預設路徑以及重新導向
在網址有錯誤的時候 vue 會直接跳一個全白的頁面然後在 console 裡面顯示錯誤給你看,不過這樣對使用者來講真的有點莫名其妙,所以我們可以用兩種方法來提升使用者的體驗,不會那麼不知所措
### 做一個路徑錯誤的 404 頁面
```javascript=
{
// 這邊就是用 * 去選擇所有頁面比對有沒有符合的路徑
// 如果沒有就會導到這個 router-link 來
path: '/:pathMatch(.*)*',
component: () => import('404 頁面的檔案路徑')
},
```
這樣就會顯示我們所設定的 404 頁面給使用者知道網址有錯誤哦
### 重新導向
```javascript
{
path: '/元件路由路徑/:pathMatch(.*)*',
redirect: {
// 重新導向到的位置
// 可以用路徑也可以使用設定好的 name
name: 'Home',
}
}
```
這樣網址有錯誤的時候就會直接被導回首頁囉
### 補充一下比對路徑的正規表達式的意思:
```javascript!
. 代表任意字元
* 代表 0 個或多個以上
.* 就變成任意字元 0 個或多個以上
```
另外,也可以習慣的將 404 頁面放到路由表的最後一個,這樣會比較知道自己要去哪裡找東西,另外,這樣的思考方式也很像後端開發路由的想法(有一致性,因為後端的路由確實是從上到下比對)
## 路由設定選項
這個會寫在 createRouter 裏面,有幾個不錯用的設定可以參考一下:
```javascript=
const router = createRouter({
// history & routes 是 vue router 起始就有的
histoiry: createWebHashHistory(),
routes,
// 為 router-link 增加啟用
linkActiveClass: 'class 名稱,bootstrap 會使用 active',
// to 是前往的頁面
// from 是從哪個頁面出發
// savePosition 是我前往頁面時,頁面的高度位置
scrollBehavior(to, from, savePosition) {
if (to.fullPath.match('頁面名稱')) {
return {
// 下一個頁面渲染好的時候的高度
top: 0,
}
}
},
scrollBehavior(to, from, savePosition) {
//也可以直接設定好高度就好,
//這樣無論切過來前高度在哪裡,
//到新頁面都會到下面 top 設定的高度
return{
top: 0,
}
}
})
```