--- 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, } } }) ```