[Vue3] 第三課 Vue Router 和 Vue Axios

2024 年 1 月 24 日
文章摘要
FakeGPT
加載中...
此內容由人工不智慧生成。

開始之前

其實這兩個東西互相之間並沒有什麼關聯,一個是 Vue3 官方推薦的路由管理工具,一個是 Vue3 中使用人數最多的 HTTP 請求發送工具。為什麼筆者要將這兩個東西放在一起去講呢?有兩個原因,第一個是因為之前兩節課,已經把 Vue 的基礎使用、Vue 元件這兩個 Vue 中最重要的概念完成了,因此剩下一些瑣碎的東西,大約就是這兩個很重要了。第二是因為這兩個東西都屬於 Vue 生態(Ecosystem)中很重要的環節,筆者希望讀者能夠藉此機會熟悉 Vue3 強大的可拓展性。

Vue Router

在講到這個東西之前,讀者需要先瞭解路由(Router)這個概念。在傳統的 Web 開發過程中,當需要實作多個站內頁面時,需要寫很多 HTML 頁面,然後透過 <a> 標籤來實現互相跳躍。

在現今化模式下的前端開發,像 Vue,可以輕鬆實現只用一個 HTML 檔案,卻能夠完成多個站內頁面渲染、跳轉的功能,這就是路由。

放到 Vue 中,路由的實現,是透過掛載不同的頁面元件來實現的。

要在 Vue 中實現路由的功能,我們要使用到 Vue Router

Vue Router 的安裝和基本使用

  1. 使用 npm 安裝 Vue Router
Terminal window
npm install vue-router@4
  1. 在專案的根目錄下創建兩個目錄:router 和 views
Terminal window
mkdir router views
  1. router 下新建 router.js 檔案:
Terminal window
touch router/router.js
  1. views 下新建測試元件並填入一些內容:
Terminal window
touch views/test.vue
echo "<script>\n</script>\n<template>\n<div>Hello, world.</div>\n</template>\n<style>\n</style>" >> views/test.vue
  1. router.js 中填入以下內容:
import { createRouter, createWebHistory } from 'vue-router';
// 宣告路由集合
// name:路由的名稱,path:路由的路徑,component:該路由對應的頁面元件
const routes = [
{ name: "test", path: "/test", component: () => import('../views/test.vue') }
]
// 宣告路由轉換器
// history:web history,routes:標準寫法是 routes: routes,但如果上面宣告的路由集合的名字爲 routes,就可以簡寫爲 routes
const router = createRouter({
history: createWebHistory(),
routes
})
// 匯出路由轉換器
export default router
  1. 在主配置 main.js 中引入路由轉換器
main.js
...
import router from './router/router.js';
const app = createApp(App)
app.use(router)
...
  1. App.vue 根元件中添加 <router-view></router-view> 標籤。

完成了以上步驟,當我們打開瀏覽器,進入 http://localhost:5173/test ,就可以看到顯示 Hello, world. 訊息的路由頁面了。

巢狀路由

從上面的配置中,我們不難看出,路由和頁面元件是一一對應的關係。在任一 Vue App 中,都有一個基本路由:path 爲 / 對應 App.vue。因此,/ 也被稱爲根路由,App.vue 也被稱爲根元件。

而我們新增的路由 /test 對應的頁面元件是 test.vue。但是,上面的步驟中我們也看到,要想將新路由在頁面上顯示出來,仍然需要在根元件上添加 <router-view></router-view> 這個標籤。這裏就涉及到一個不是很好理解的知識點——巢狀路由。

上面的例子中,我們可以將 /test 中的斜線看作是(事實上也就是)根路由 /,也就是說,/test 路由實際上是“掛”在根路由上,對應着的,其元件 test.vue 也要相應放到根元件中才能顯示。這就是巢狀路由,即子路由必須要掛到父路由中才能夠藉由父路由的顯示而顯示。

接下來我們繼續思考一個問題:我們剛剛只不過是在App.vue中添加了一個 <router-view></router-view> 標籤,用以代表 App.vue 這個元件對應的路由(也就是根路由)下掛載的子路由對應的元件。那麼,是否是只要開啓了路由,App.vue中就只能放 <router-view>\</router-view> 標籤呢?答案顯然是否定的。讓我們爲 App.vue 加一點東西:

<template>
<div>這是原本顯示在根元件中的內容哦!</div>
<router-view></router-view>
</template>

顯示效果如下: 巢狀路由

我們可以看到,原本在 App.vue 中的內容也正確地被顯示了。因此,我們得出了一個令人驚悚的結論——似乎,頁面元件也可以像功能元件那樣,作爲上一級頁面的一部分來顯示,而不是全部。

恭喜你,如果你理解到這一層,那麼代表着你會對路由和頁面元件有了一個比較深入的認識,而不僅僅侷限於一個路由對應一個頁面。好,那麼現在我們總結出來的結論是:一個路由對應一個頁面元件,而不是一個路由對應一個頁面。

也就是說,如果根路由 / 下除了掛載 /test 路由,還掛載了其他的什麼別的路由,這些路由也都將作爲根元件的一部分去顯示,當我們在這些路由之間切換的時候,事實上,是根元件中 <router-view></router-view> 標籤所代表的頁面元件之間的切換。

OK,理解了這個概念,我們就可以繼續進行下去了。接下來我們講的是:多層巢狀路由。

既然普通的頁面元件能夠放到根元件裏面,那麼頁面元件中是不是也可以繼續放其他的頁面元件呢?當然可以了!畢竟每個子頁面都是父頁面的一部分嘛。所以理論上來講,路由可以一直套下去。比如這一段:/test/demo/0nlineTek/web/...。那麼,多層巢狀路由該怎麼實現呢?很簡單,我們首先要在宣告的 routes 集合裏面爲需要的路由添加 children 屬性:

router.js
const routes = [
{
name: "test",
path: "/test",
component: () => import('../views/test.vue'),
children: [
{ name: "demo", path: "/test/demo", component: () => import('../views/demo.vue') }
]
}
]

然後在 test.vue 的對應位置再加上一個 <router-view><router-view> 標籤就好了。

動態路由匹配

很多時候,我們需要將給定匹配模式的路由對應到同一個元件。 例如,我們可能有一個 User 元件,它應該對所有使用者進行渲染,但使用者 ID 不同。 在 Vue Router 中,我們可以在路徑中使用一個動態欄位來實現,我們稱之為路徑參數

router.js
const routes = [
// 動態欄位以冒號開始
{ path: '/users/:id', component: User },
]

那麼現在,/users/xiaoming/users/xiaogang這類的路由均會映射到 User 元件。

我們在 User 元件內部,也可以使用$route.params.id拿到欄位 id 的值。

編程式導航

如果我們想要在一個路由下實現跳轉到另一個路由,當然可以使用 <a> 標籤,但更推薦的方式是使用編程式導航:

import { useRouter } from 'vue-router';
const router = useRouter()
const navigateTo = (route) => {
router.push(route)
}

其中,useRouter().push() 方法可以從當前路由跳轉到其餘路由。其引數可以是路由的 name 或者路由的 path。

如果你想要在跳轉到另一個路由的時候,向另一個路由傳送引數,可以使用 params 或 query 引數:

// 當使用 params 引數時,不能配合 path,必須使用 name,params 引數不會顯示到 url 中,但重新整理頁面後 params 引數失效。(經過測試,此方法暫不可用,似乎是 Vue Router 的 bug)
router.push({name: 'User', params: { username: "xiaoming" }})
// 當使用 query 引數時,可以配合 path 或 name,query 引數一定會顯示到 url 中,但重新整理頁面後 query 引數會得到保留。
router.push({path: '/user', query: { username: "xiaoming" }})

終點路由用 useRoute().query 接收。

導航守衛

在瞭解這個知識之前,我們首先要給自己定下一個規矩:好好設計路由結構,路由結構切勿過於複雜。能用功能元件解決的問題,就儘量別用路由。否則,下面要講的東西以後用起來,一定會要了你的命。

我們通常都有這樣的需求:只有用戶完成了登入動作,纔能進入某些路由顯示頁面,否則就重定向到登入頁面。

這個時候,我們就需要一把“鎖”來守衛住我們的路由,只有符合條件,纔將路由放行,其餘情況下統統攔下。Vue Router 的導航守衛功能應運而生。

簡單來講,所謂的導航守衛,就是在用戶不論透過什麼方式(不管是頁面內導航,還是直接在位址欄中輸入 url)進入路由前,加裝一個檢查站攔截用戶的流量,將現有條件和預設條件進行比對,滿足預設條件則放行,反之則不放行。

我們一般使用的導航守衛都是全局前置守衛:

router.beforeEach(async (to, from) => {
if (
// 检查用户是否已登录
!isAuthenticated &&
// ❗️ 避免无限重定向
to.name !== 'Login'
) {
// 将用户重定向到登录页面
return { name: 'Login' }
}
})

接下來筆者解釋一下回呼函式中兩個引數的意義:

  1. to:表示即將要跳轉到的路由物件。
  2. from:表示從哪個路由物件跳轉的。

如果有讀者去閱讀 Vue Router 的相關文檔,請忽略 next 引數,這個引數官方並不推薦使用,也不一定會在哪一版本中移除。

Vue Router 相關內容就講到這裏。其餘內容請自行參閱 Vue Router 官方文檔。

Axios

在原生 JS 中,我們使用 JQuery 包中提供的 $ajax() 函式來向後端發送請求。那麼在 Vue3 中,我們使用和它非常相像的一個工具,名叫 axios。

  1. 安裝 axios
Terminal window
npm install --save axios
  1. 使用 axios 發送請求:
import axios from 'axios';
axios({
url: "https://api.example.com/api",
method: "POST",
data: {
need: "yes"
}
})
.then((res) => {
console.log(res)
})
.catch((err) => {
console.log(err)
})
[Vue3] 第三課 Vue Router 和 Vue Axios
https://blog.kynix.tw/posts/1731050659021/
作者
Adrian Chen
建檔時間
2024 年 1 月 24 日
協議
BY-NC-SA 4.0
姓名標示-非商業性-相同方式分享 4.0 國際