{%hackmd BJrTq20hE %} ###### tags: `Vue` `composition API` # 從composition API 開始VUE的生活- Vue-Router 基礎入門 Vue-Router是一款可以讓使用Vue框架所寫的SPA網頁很簡單的切換的工具。 ## 如何建立Vue-Router 如果是使用vite的話在環境安裝時選擇使用Vue-Router就行 1.輸入npm install vue-router@4 ``` npm install vue-router@4 ``` 2.建立router資料夾與index.js,如下圖 ![](https://i.imgur.com/zpIMXPM.jpg) 3.index.js裡面的東西。 我直接從vite所建立的專案複製而來 ```javascript= import { createRouter, createWebHistory } from 'vue-router' import HomeView from '../views/HomeView.vue' const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), routes: [ { path: '/', name: 'home', component: HomeView }, { path: '/about', name: 'about', component: () => import('../views/AboutView.vue') } ] }) export default router ``` 以上Vue-Router的前置工作就算完成了 ## 如何建立路由? ### 先建立頁面再建立路由。 1.在views這個資料夾建立一個TestView.vue的頁面/檔案 ![](https://i.imgur.com/nJ74Ow4.jpg) 2.在router資料夾下的index.js新增剛剛的page ```javascript= import { createRouter, createWebHistory } from 'vue-router' import HomeView from '../views/HomeView.vue' const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), routes: [ { path: '/', name: 'home', component: HomeView }, { path: '/about', name: 'about', component: () => import('../views/AboutView.vue') }, // 建立新的test頁面路由 { path: '/test', name: 'test', // 記得import TestView.vue component: () => import('../views/TestView.vue') } ] }) export default router ``` :::info 關於路由內component的import方式。 1.靜態載入,先import HomeView.vue 之後再放入路由之中,好處是如果網頁屬於靜態網頁可以預先載好內容,在切換頁面時沒有載入的時間。 ``` component: HomeView ``` 2.動態載入,需要進入到TestView.vue再載入,優點是可以取得即時的網頁內容,缺點是有載入的時間。 ``` component: () => import('../views/TestView.vue') ``` ::: 3.在想顯示TestView.vue這一頁內容的page使用Vue-Router 這邊以App.vue為例子: ```javascript= <script setup> // import RouterLink, RouterView 在template中使用 import { RouterLink, RouterView } from 'vue-router' </script> ``` ```htmlembedded= <template> <nav> <RouterLink to="/">Home</RouterLink> <RouterLink to="/about">About</RouterLink> <RouterLink to="/test">test</RouterLink> </nav> <RouterView /> </template> ``` :::info RouterLink在網頁中是<a></a> <RouterView />則是顯示路由切換頁面的地方 ::: 在頁面會出現 HOME About test 個別點擊後會出現以下畫面 ![](https://i.imgur.com/YHcPyMD.jpg) ![](https://i.imgur.com/HX9t5HZ.jpg) ![](https://i.imgur.com/AFKsBkE.jpg) ## 子路由的建立 簡單的來說就是頁面中的頁面。 以下範例是在TestView.vue中建立一個nav分別連接A、B、C三個page。 1.原則是,先建立頁面再建立路由。 2.在views下建立一個資料夾Test,並在資料夾中建立A、B、C三個page ```htmlembedded= <template> <h1>A</h1> </template> ``` ```htmlembedded= <template> <h1>B</h1> </template> ``` ```htmlembedded= <template> <h1>C</h1> </template> ``` ![](https://i.imgur.com/qR90WRO.jpg) 3.到router資料夾下的index.js新增text的子路由A、B、C三個page ```javascript= import { createRouter, createWebHistory } from 'vue-router' import HomeView from '../views/HomeView.vue' const router = createRouter({ history: createWebHashHistory(), routes: [ { path: '/', name: 'home', component: HomeView }, { path: '/about', name: 'about', component: () => import('../views/AboutView.vue') }, { // 直接在test的路由下新增一個children:[] // 並在裡面新增A B C三個路由 // 另外可以新增切換到test頁中預設要顯示的子路由 path: '/test', name: 'test', component: () => import('../views/TestView.vue'), children:[ // 預設顯示的路由為AView.vue,path:''代表與/test一樣 // name: 就不能設'a'了,name可以當成唯一,如果有一樣的name預設功能就不會出現了。 { path: '', name: 'defaultA', component: () => import('../views/Test/AView.vue') }, { path: 'a', name: 'a', component: () => import('../views/Test/AView.vue') }, { path: 'b', name: 'b', component: () => import('../views/Test/BView.vue') }, { path: 'c', name: 'c', component: () => import('../views/Test/CView.vue') }, ] }, ] }) export default router ``` 4.回到TestView.vue中import RouterView、RouterLink ```javascript= <script setup> import { RouterLink, RouterView } from 'vue-router'; </script> ``` ```htmlembedded= <template> <h2>test</h2> <nav> <RouterLink to="/test/a">A</RouterLink> <RouterLink to="/test/b">B</RouterLink> <RouterLink to="/test/c">C</RouterLink> </nav> <RouterView /> </template> ``` 點擊test後會出現 A B C,分別點擊後會出現以下畫面 ![](https://i.imgur.com/LbpEv1L.jpg) ![](https://i.imgur.com/xuiaFmi.jpg) ![](https://i.imgur.com/lAgQQ2k.jpg) ## 動態路由的建立 動態路由可以透過<RouterLink to=""></RouterLink>或是useRouter.push、與$useRouter.params.id搭配API取得特定資料後顯示在頁面上。 以下的範例會在TestView.vue的子路由中建立一個動態路由,並使用useRoute取得動態路由的id與path 1.建立DynamicViwe.vue ```javascript= <script setup> import { useRoute } from 'vue-router'; const route = useRoute() </script> ``` ```htmlembedded= <template> <h2>動態頁面</h2> <h2>RouterPath:{{route.path}}</h2> <h2>RouterId:{{route.params.id}}</h2> </template> ``` 2.到router資料夾下的index.js新增text的子路由 ```javascript= import { createRouter, createWebHistory } from 'vue-router' import HomeView from '../views/HomeView.vue' const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), routes: [ { path: '/', name: 'home', component: HomeView }, { path: '/about', name: 'about', component: () => import('../views/AboutView.vue') }, { path: '/test', name: 'test', component: () => import('../views/TestView.vue'), children:[ { path: '', name: 'defaultA', component: () => import('../views/Test/AView.vue') }, { path: 'a', name: 'a', component: () => import('../views/Test/AView.vue') }, { path: 'b', name: 'b', component: () => import('../views/Test/BView.vue') }, { path: 'c', name: 'c', component: () => import('../views/Test/CView.vue') }, { // 動態路由使用:id path: 'dynamic/:id', name: 'dynamicPage', component: () => import('../views/Test/DynamicPageView.vue') }, ] }, { path: '/:pathMatch(.*)*', name: 'notFound', component: () => import('../views/FindNoPageView.vue') }, ] }) export default router ``` 3.到TextView.vue新增一個RouterLink ```javascript= <script setup> import { RouterLink, RouterView } from 'vue-router'; </script> ``` ```htmlembedded= <template> <h2>test</h2> <nav> <RouterLink to="/test/a">A</RouterLink> <RouterLink to="/test/b">B</RouterLink> <RouterLink to="/test/c">C</RouterLink> <!-- 456123 這一串數字就是動態加入的路由,可以依照需求修改 --> <RouterLink to="/test/dynamic/456123">Dynamic</RouterLink> </nav> <RouterView /> </template> ``` 最後點擊dynamic會出現以下畫面 ![](https://i.imgur.com/UVG9Ndy.jpg) ## 使用Vue-Router製作一個404找不到頁面的功能 有的時候會不小心打錯網址,在沒有製作404找不到頁面時畫面會停在前一個畫面,有了404頁面就可以知道打錯網址。 1.在views資料夾下建立一個FindNoPageView.vue ```htmlembedded=<template> <h1>404找不到這一頁</h1> </template> ``` 2.到router資料夾下的index.js新增FindNoPageView.vue的路由 ```javascript= import { createRouter, createWebHistory } from 'vue-router' import HomeView from '../views/HomeView.vue' const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), routes: [ { path: '/', name: 'home', component: HomeView }, { path: '/about', name: 'about', component: () => import('../views/AboutView.vue') }, { path: '/test', name: 'test', component: () => import('../views/TestView.vue'), children:[ { path: '', name: 'defaultA', component: () => import('../views/Test/AView.vue') }, { path: 'a', name: 'a', component: () => import('../views/Test/AView.vue') }, { path: 'b', name: 'b', component: () => import('../views/Test/BView.vue') }, { path: 'c', name: 'c', component: () => import('../views/Test/CView.vue') }, { path: 'dynamic/:id', name: 'dynamicPage', component: () => import('../views/Test/DynamicPageView.vue') }, ] }, // 404功能的路由建立 { path: '/:pathMatch(.*)*', name: 'notFound', component: () => import('../views/FindNoPageView.vue') }, ] }) export default router ``` :::info path:'/:pathMatch(.*)*' 代表所有的頁面,所以要放在routes:{[]},陣列的最後面。如果放在最前面,那動態路由有可能會被path:'/:pathMatch(.*)*'攔截然後直接進入到404頁面。 pathMatch可以自訂。 ::: 網址輸入錯誤則會出現 ![](https://i.imgur.com/XXdYtGT.jpg) ## useRouter的方法 push與replace的差別 這兩著的功能一樣都是讓網頁進入到另一個頁面,區別在push會留下歷史紀錄,replace則不會留下歷史紀錄 以下是範例在HomeView.vue中加入3秒後導向AView.vue功能 push ```javascript= setTimeout(()=>{ router.push('/test/a') },3000) ``` 在home頁面停留3秒後會切換到AView.vue中,但點選上一頁回到home replace ```javascript= setTimeout(()=>{ router.replace({ name:'a', }) },3000) ``` 也可以寫成router.replace('/test/a') 在home頁面停留3秒後會切換到AView.vue中,但點選上一頁則不會出現home 延伸閱讀 --- [Router 方法](https://router.vuejs.org/zh/api/index.html#addroute) ## 不同的歷史模式 ### createWebHistory與createWebHashHistory的區別 在Vue-Router預設的模式是createWebHistory,但是在這個模式需要後端的支援才能運作,[服务器配置示例](https://router.vuejs.org/zh/guide/essentials/history-mode.html#%E6%9C%8D%E5%8A%A1%E5%99%A8%E9%85%8D%E7%BD%AE%E7%A4%BA%E4%BE%8B),如果沒有後端支援會造成往頁部屬後點即RouterLink沒有頁面跑出,但是輸入網址則頁面可以正常出現的情況 createWebHashHistory則沒有以上的問題,但是會使SEO的效果變差,因為Google爬蟲只能爬到用JS處理後的網頁,也不知道有沒有爬完整。 最直接的區別就在網址有沒有# createWebHistory ![](https://i.imgur.com/0E6QM0b.jpg) createWebHashHistory ![](https://i.imgur.com/InbeJCq.jpg) 在使用vue開發網頁時沒有SSR的效過service side randen,所以需要Nuxt 或 preranden來增加SEO的效果 以下是切換成createWebHashHistory的範例 1.到router資料夾下的index.js 2.把createWebHistory換成createWebHashHistory ```javascript= import { createRouter, createWebHashHistory } from 'vue-router' import HomeView from '../views/HomeView.vue' const router = createRouter({ // 切換成createWebHashHistory history: createWebHashHistory(), routes: [ { path: '/', name: 'home', component: HomeView }, { path: '/about', name: 'about', component: () => import('../views/AboutView.vue') }, { path: '/test', name: 'test', component: () => import('../views/TestView.vue'), children:[ { path: '', name: 'defaultA', component: () => import('../views/Test/AView.vue') }, { path: 'a', name: 'a', component: () => import('../views/Test/AView.vue') }, { path: 'b', name: 'b', component: () => import('../views/Test/BView.vue') }, { path: 'c', name: 'c', component: () => import('../views/Test/CView.vue') }, { path: 'dynamic/:id', name: 'dynamicPage', component: () => import('../views/Test/DynamicPageView.vue') }, ] }, { path: '/:pathMatch(.*)*', name: 'notFound', component: () => import('../views/FindNoPageView.vue') }, ] }) export default router ``` ## 路由傳query與資料 [不只懂 Vue 語法:如何透過路由實現跨頁面傳遞資料?](https://ithelp.ithome.com.tw/articles/10269680) 參考資料 --- [Vue3 + Vite 快速上手 Get Startrd EP8 - Vue-Router 基礎入門,SPA網頁輕鬆上手 !](https://www.youtube.com/watch?v=5YzSuKfwWv4) [Vue Router](https://router.vuejs.org/)