在構建單頁應用(SPA)時,路由管理是一個至關重要的部分。Vue Router 是 Vue.js 官方提供的路由解決方案,與 Vue 3 的 Composition API 緊密結合。在這篇文章中,我們將探討如何結合 Vue Router 和 TypeScript,實現型別安全的路由管理,確保在開發過程中享受 TypeScript 帶來的靜態型別檢查和自動補全功能。
Vue Router 是 Vue 生態系統中的核心部分,負責應用內部不同視圖之間的導航。隨著應用的規模增長,路由配置可能會變得複雜且難以管理。將 TypeScript 引入路由管理可以帶來以下優勢:
首先,我們需要在 Vue 3 項目中安裝 Vue Router。
bun add vue-router
安裝完成後,我們需要在項目中配置 Vue Router。
接下來,我們將創建一個簡單的路由配置文件,並使用 TypeScript 來強化路由管理。
(檔案: src/router/index.ts
)
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
export enum RoutesStatus {
Home = 'Home',
About = 'About',
User = 'User'
}
// 定義路由配置的型別
const routes: Array<RouteRecordRaw> = [
{
path: '/',
name: RoutesStatus.Home,
component: () => import('../pages/Home.vue'),
},
{
path: '/about',
name: RoutesStatus.About,
component: () => import('../pages/About.vue'),
},
];
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL ?? ''),
routes,
});
export default router;
在這個例子中,我們使用了 RouteRecordRaw
來明確定義路由的結構和型別,確保每個路由的 path
、name
和 component
都符合預期。
接下來,我們需要在應用的入口文件中將 Vue Router 集成到 Vue 應用中。
(src/main.ts
)
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
const app = createApp(App);
app.use(router);
app.mount('#app');
這樣,我們的 Vue 應用就具備了路由功能,並且通過 TypeScript 強化了路由配置的型別檢查。
在實際應用中,很多路由需要動態參數。這裡我們來看一下如何在 Vue Router 中處理帶參數的路由,並結合 TypeScript 確保參數的正確性。 (src/router/indext.ts
)
const routes: Array<RouteRecordRaw> = [
{
path: '/',
name: RoutesStatus.Home,
component: () => import('../pages/Home.vue'),
},
{
path: '/user/:id',
name: RoutesStatus.User,
component: () => import('../pages/User.vue'),
props: (route) => ({ id: Number(route.params.id) }),
meta: {
isRequireAuth: true,
},
},
];
在這個範例中,我們定義了一個帶有 :id
參數的動態路由,並將路由參數轉換為 props
傳遞給組件。這種方式使我們能夠在組件中直接使用 props
,同時 TypeScript 會自動推斷 id
的型別。
Vue Router 提供了全局和路由級別的導航守衛,用於在導航到某個路由之前進行驗證或執行某些邏輯操作。使用 TypeScript 可以讓導航守衛更加安全和明確。
router.beforeEach(to => {
if (!to.meta.isRequireAuth) return true;
// 這裡設定如果需要驗證則放行
return false;
});
在這個例子中,router 的 metaData
如果不需要驗證則直接放行,否則不放行,中間的部分可以去判斷有無權限,有的話放行沒的話不放行。
我們這裡簡單做一個驗證是否通過的範例: (檔案:src/composables/useAuth.ts
)
import * as zod from 'zod';
export const validateSchema = zod.object({
isAuth: zod.boolean(),
});
export type ValidateSchema = zod.infer<typeof validateSchema>;
export const useAuth = () => {
const checkIfAllowPass = async (): Promise<boolean> => {
const token = localStorage.getItem('auth');
if (token === null || token.trim() === '') return false;
const response = await fetch('https://api.example.com/validateToken', {
headers: {
Authorization: `Bearer ${token}`
}
});
const authResult = await response.json();
const validator = await validateSchema.safeParseAsync(authResult);
if (!validator.success) {
console.error(validator.error.errors);
return false;
}
return validator.data.isAuth;
};
return {
checkIfAllowPass,
};
};
export type UseAuth = typeof useAuth;
這時我們導航守衛,可以改成這樣處理 (檔案 : src/router/index.ts
)
// 上方記得 import { useAuth } from '../composables/useAuth';
router.beforeEach(async (to) => {
if (!to.meta.isRequireAuth) return true;
const { checkIfAllowPass } = useAuth();
const isOkToPass = await checkIfAllowPass();
if (isOkToPass) {
return;
}
return false;
});
為了避免直接操作 URL 字符串,Vue Router 支持使用命名路由進行導航,這樣可以使導航更加安全和可靠。
// 使用命名路由進行導航
router.push({ name: RoutesStatus.User, params: { id: 123 } });
在這裡,TypeScript 可以自動檢查 params
是否符合 User
路由的要求,避免我們傳入錯誤的參數或缺少必要的參數。
我們用 Home 頁面作為主要範例 Home.vue
(檔案: src/pages/Home.vue
)
<script setup lang="ts">
import { useRouter } from 'vue-router'
import { RoutesStatus } from '../router';
const router = useRouter();
const goToUserPage = (): void => {
router.push({ name: RoutesStatus.User, params: { id: 123 } });
};
</script>
<template>
<h1>This is Home page</h1>
<button @click="goToUserPage">Go to User Page</button>
</template>
當我們需要在 Vue 應用中多次使用路由參數時,可以考慮擴展全局型別,使得我們能夠在整個應用中共享路由型別。
// src/types/vue-router.d.ts
import 'vue-router';
declare module 'vue-router' {
interface RouteMeta {
isRequireAuth?: boolean;
}
}
這樣做的好處是,我們可以在全局範圍內擴展 RouteMeta
的型別定義,比如為每個路由添加 requiresAuth
屬性,方便在導航守衛中使用。
通過結合 Vue Router 和 TypeScript,我們可以實現型別安全的路由管理,不僅提升了代碼的可讀性和可維護性,還減少了因路由錯誤帶來的潛在問題。本文介紹了如何安裝和配置 Vue Router、處理動態路由、導航守衛、命名路由導航等常見場景,並展示了 TypeScript 如何為我們的開發提供強大的型別檢查支持。
接下來的文章中,我們將探討如何進一步使用 Vue Router 和 TypeScript,在大型應用中實現複雜的導航邏輯與狀態管理。