Vue Router 是 Vue 官方的客戶端路由解決方案。
客戶端路由的作用是在單頁應用 (SPA) 中將瀏覽器的 URL 和用戶看到的內容綁定起來。當用戶在應用中瀏覽不同頁面時,URL 會隨之更新,但頁面不需要從服務器重新加載。
Vue Router 基于 Vue 的組件系統構建,你可以通過配置路由來告訴 Vue Router 為每個 URL 路徑顯示哪些組件。
訪問路徑 ======> 組件
安裝Vue Router
npm install vue-router
yarn add vue-router
pnpm add vue-router
在package.json文件中顯示vue-router版本代表安裝成功
Vue Router使用
路由配置文件如下:
//引入創建路由
import { createRouter, createWebHistory } from "vue-router";
//引入組件
import Home from "@/components/Home.vue";
import Poclist from "@/components/Poclist.vue";
import Portscan from "@/components/Portscan.vue";//創建路由
const router = createRouter({history: createWebHistory(),routes: [{path: "/home",component: Home,},{path:"/poclist",component:Poclist},{path:"/portscan",component:Portscan}]
});export default router
注冊路由器插件
一旦創建了我們的路由器實例,我們就需要將其注冊為插件,這一步驟可以通過調用 use() 來完成。
main.ts文件
import { createApp } from 'vue'
import App from './App.vue'
import router from '@/router/index'createApp(App).use(router).mount('#app')
或等價于:
import { createApp } from 'vue'
import App from './App.vue'
import router from '@/router/index'const app = createApp(App)app.use(router)
app.mount('#app')
和大多數的 Vue 插件一樣,use() 需要在 mount() 之前調用。
APP.vue
<template><div class="app"><h3 class="title">Vue路由測試</h3><!-- 導航區 --><div class="navigate"><RouterLink to="/home" active-class="active">首頁</RouterLink><RouterLink to="/portscan" active-class="active">端口掃描</RouterLink><RouterLink to="/poclist" active-class="active">POC列表</RouterLink></div><!-- 展示區 --><div class="main-content"><RouterView></RouterView></div></div>
</template><script lang="ts" setup name="APP">
</script>
效果如下:
路由組件通常存放在
pages
或views
文件夾,一般組件通常存放在components
文件夾。通過點擊導航,視覺效果上“消失” 了的路由組件,默認是被卸載掉的,需要的時候再去掛載。
不同的歷史模式
在創建路由器實例時,history 配置允許我們在不同的歷史模式中進行選擇。
共支持 HASH模式、Memory 模式、HTML5 模式
Hash 模式
hash 模式是用 createWebHashHistory() 創建的:
import { createRouter, createWebHashHistory } from 'vue-router'const router = createRouter({history: createWebHashHistory(),routes: [//...],
})
它在內部傳遞的實際 URL 之前使用了一個哈希字符(#)。由于這部分 URL 從未被發送到服務器,所以它不需要在服務器層面上進行任何特殊處理。不過,它在 SEO 中確實有不好的影響。如果你擔心這個問題,可以使用 HTML5 模式。
例如:
http://127.0.0.1:4000/#/index
Memory 模式
Memory 模式不會假定自己處于瀏覽器環境,因此不會與 URL 交互也不會自動觸發初始導航。這使得它非常適合 Node 環境和 SSR。它是用 createMemoryHistory() 創建的,并且需要你在調用 app.use(router) 之后手動 push 到初始導航。
import { createRouter, createMemoryHistory } from 'vue-router'
const router = createRouter({history: createMemoryHistory(),routes: [//...],
})
雖然不推薦,你仍可以在瀏覽器應用程序中使用此模式,但請注意它不會有歷史記錄,這意味著你無法后退或前進。
HTML5 模式(推薦)
用 createWebHistory() 創建 HTML5 模式,推薦使用這個模式:
import { createRouter, createWebHistory } from 'vue-router'const router = createRouter({history: createWebHistory(),routes: [//...],
})
當使用這種歷史模式時,URL 會看起來很 “正常”,例如 https://example.com/user/id
不過,問題來了。由于我們的應用是一個單頁的客戶端應用,如果沒有適當的服務器配置,用戶在瀏覽器中直接訪問 https://example.com/user/id,就會得到一個 404 錯誤。這就尷尬了。
不用擔心: 要解決這個問題,你需要做的就是在你的服務器上添加一個簡單的回退路由。如果 URL 不匹配任何靜態資源,它應提供與你的應用程序中的 index.html 相同的頁面。
具體配置可以參考官網:
https://router.vuejs.org/zh/guide/essentials/history-mode.html
例如Nginx:
location / {try_files $uri $uri/ /index.html;
}
這有一個注意事項。你的服務器將不再報告 404 錯誤,因為現在所有未找到的路徑都會顯示你的 index.html 文件。為了解決這個問題,你應該在你的 Vue 應用程序中實現一個萬能的路由來顯示 404 頁面。
const router = createRouter({history: createWebHistory(),routes: [{ path: '/:pathMatch(.*)', component: NotFoundComponent }],
})
另外,如果你使用的是 Node.js 服務器,你可以通過在服務器端使用路由器來匹配傳入的 URL,如果沒有匹配到路由,則用 404 來響應,從而實現回退。
to的兩種寫法
<!-- 第一種:to的字符串寫法 -->
<router-link active-class="active" to="/home">主頁</router-link><!-- 第二種:to的對象寫法 -->
<router-link active-class="active" :to="{path:'/home'}">Home</router-link>
命名路由
當創建一個路由時,我們可以選擇給路由一個 name:
然后我們可以使用 name 而不是 path 來傳遞 to 屬性給 :
<router-link :to="{ name: 'profile', params: { username: 'erina' } }">User profile
</router-link>
所有路由的命名都必須是唯一的。如果為多條路由添加相同的命名,路由器只會保留最后那一條。
嵌套路由
一些應用程序的 UI 由多層嵌套的組件組成。在這種情況下,URL 的片段通常對應于特定的嵌套組件結構,例如:
/user/johnny/profile /user/johnny/posts
┌──────────────────┐ ┌──────────────────┐
│ User │ │ User │
│ ┌──────────────┐ │ │ ┌──────────────┐ │
│ │ Profile │ │ ●────────────? │ │ Posts │ │
│ │ │ │ │ │ │ │
│ └──────────────┘ │ │ └──────────────┘ │
└──────────────────┘ └──────────────────┘
通過 Vue Router,你可以使用嵌套路由配置來表達這種關系。
children 配置只是另一個路由數組,就像 routes 本身一樣,所以支持不斷地嵌套
當你訪問不存在的路由時,例如/pocinfo/111
,會顯示空白。,因為沒有匹配到嵌套路由。也許你確實想在那里渲染一些東西。在這種情況下,你可以提供一個空的嵌套路徑:
嵌套路由也支持命名
可通過瀏覽器插件查看
路由傳遞參數
query參數
傳遞參數
<!-- 跳轉并攜帶query參數(to的字符串寫法) -->
<router-link to="/news/detail?a=1&b=2&content=歡迎你">跳轉
</router-link><!-- 跳轉并攜帶query參數(to的對象寫法) -->
<RouterLink :to="{//name:'xiang', //用name也可以跳轉path:'/news/detail',query:{id:news.id,title:news.title,content:news.content}}"
>{{news.title}}
</RouterLink>
接收參數:
import {useRoute} from 'vue-router'
const route = useRoute()
// 打印query參數
console.log(route.query)
params參數
傳遞參數
<!-- 跳轉并攜帶params參數(to的字符串寫法) -->
<RouterLink :to="`/news/detail/001/新聞001/內容001`">{{news.title}}</RouterLink><!-- 跳轉并攜帶params參數(to的對象寫法) -->
<RouterLink :to="{name:'xiang', //用name跳轉params:{id:news.id,title:news.title,content:news.title}}"
>{{news.title}}
</RouterLink>
接收參數
import {useRoute} from 'vue-router'
const route = useRoute()
// 打印params參數
console.log(route.params)
備注1:傳遞
params
參數時,若使用to
的對象寫法,必須使用name
配置項,不能用path
。備注2:傳遞
params
參數時,需要提前在規則中占位。
路由規則的props配置
布爾模式
當 props 設置為 true 時,route.params 將被設置為組件的 props。
const routes = [{name: "poclist",path: "/poclist",component: Poclist,children:[{name:"pocinfo",path:"pocinfo",component:Pocinfo,props:true}
]
Poclist.vue
<RouterLink :to="{name: 'pocinfo',params:{id: pocs.id,title: pocs.title,content: pocs.content}}">{{ pocs.title }}</RouterLink>
Pocinfio.vue
<template><ul class="news-list"><li>編號:{{ id }}</li><li>標題:{{ title }}</li><li>內容:{{ content }}</li></ul>
</template><script setup lang='ts'>
// import { ref,reactive,toRefs} from 'vue'// import { RouterView,useRoute } from 'vue-router'defineProps(["id","title","content"])
replace屬性
-
作用:控制路由跳轉時操作瀏覽器歷史記錄的模式。
-
瀏覽器的歷史記錄有兩種寫入方式:分別為
push
和replace
:- ```push```是追加歷史記錄(默認值)。 - `replace`是替換當前記錄。
-
開啟
replace
模式:
<RouterLink replace .......>News</RouterLink>
編程式導航
除了使用 創建 a 標簽來定義導航鏈接,我們還可以借助 router 的實例方法,通過編寫代碼來實現。
當你點擊 <router-link> 時,內部會調用這個方法,所以點擊 <router-link :to="..."> 相當于調用 router.push(...) :
該方法的參數可以是一個字符串路徑,或者一個描述地址的對象。例如:
// 字符串路徑
router.push('/users/eduardo')// 帶有路徑的對象
router.push({ path: '/users/eduardo' })// 命名的路由,并加上參數,讓路由建立 url
router.push({ name: 'user', params: { username: 'eduardo' } })// 帶查詢參數,結果是 /register?plan=private
router.push({ path: '/register', query: { plan: 'private' } })// 帶 hash,結果是 /about#team
router.push({ path: '/about', hash: '#team' })
注意:如果提供了 path,params 會被忽略,如需要使用params是,需要提供路由的name 或手寫完整的帶有參數的 path :
const username = 'eduardo'
// 我們可以手動建立 url,但我們必須自己處理編碼
router.push(`/user/${username}`) // -> /user/eduardo
// 同樣
router.push({ path: `/user/${username}` }) // -> /user/eduardo
// 如果可能的話,使用 `name` 和 `params` 從自動 URL 編碼中獲益
router.push({ name: 'user', params: { username } }) // -> /user/eduardo
// `params` 不能與 `path` 一起使用
router.push({ path: '/user', params: { username } }) // -> /user
替換當前位置
它的作用類似于 router.push,唯一不同的是,它在導航時不會向 history 添加新記錄,正如它的名字所暗示的那樣——它取代了當前的條目。
也可以直接在傳遞給 router.push 的 to 參數中增加一個屬性 replace: true :
router.push({ path: '/home', replace: true })
// 相當于
router.replace({ path: '/home' })
重定向
重定向也是通過 routes 配置來完成,下面例子是從/ 重定向到 /home:
{path:'/',redirect:'/home'
}
別名
重定向是指當用戶訪問 /home 時,URL 會被 / 替換,然后匹配成 /。那么什么是別名呢?
將 / 別名為 /home,意味著當用戶訪問 /home 時,URL 仍然是 /home,但會被匹配為用戶正在訪問 /。
上面對應的路由配置為:
const routes = [{ path: '/', component: Homepage, alias: '/home' }]