在 Vue 3 中使用 TypeScript 实现路由守卫,通常依赖于 `vue-router` 库。`vue-router` 提供了全局前置守卫、全局后置钩子、路由独享守卫以及组件内的守卫等多种方式来控制导航行为。
### 全局前置守卫
全局前置守卫通常用于权限验证、登录检查等场景。通过 `router.beforeEach` 方法可以拦截所有导航请求,并根据条件决定是否允许导航继续执行。
```ts
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
import { useUserStore } from '@/stores/userStore' // 假设你使用 Pinia 管理状态
const routes: Array<RouteRecordRaw> = [
{
path: '/login',
name: 'Login',
component: () => import('@/views/Login.vue')
},
{
path: '/dashboard',
name: 'Dashboard',
component: () => import('@/views/Dashboard.vue'),
meta: { requiresAuth: true } // 添加 meta 字段表示该路由需要认证
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
router.beforeEach((to, from, next) => {
const userStore = useUserStore()
const isAuthenticated = userStore.isAuthenticated // 从 Pinia 中获取用户认证状态
if (to.meta.requiresAuth && !isAuthenticated) {
// 如果目标路由需要认证且用户未登录,则跳转到登录页
next({ name: 'Login' })
} else {
// 否则继续导航
next()
}
})
export default router
```
### 路由独享守卫
路由独享守卫是指为某个特定的路由配置的守卫逻辑,适用于需要对特定页面进行特殊处理的情况。
```ts
const routes: Array<RouteRecordRaw> = [
{
path: '/profile',
name: 'Profile',
component: () => import('@/views/Profile.vue'),
beforeEnter: (to, from, next) => {
const userStore = useUserStore()
if (userStore.isAuthenticated) {
next()
} else {
next({ name: 'Login' })
}
}
}
]
```
### 组件内守卫
组件内守卫允许在组件内部定义导航逻辑,适用于需要根据组件状态进行导航控制的情况。常用的组件内守卫包括 `beforeRouteEnter`、`beforeRouteUpdate` 和 `beforeRouteLeave`。
```ts
<script setup lang="ts">
import { beforeRouteEnter } from 'vue-router'
import { useUserStore } from '@/stores/userStore'
const userStore = useUserStore()
beforeRouteEnter((to, from, next) => {
if (userStore.isAuthenticated) {
next()
} else {
next({ name: 'Login' })
}
})
</script>
```
### 完整示例
以下是一个完整的示例,展示了如何在 Vue 3 + TypeScript 项目中配置路由守卫:
#### 1. 安装依赖
确保你已经安装了 `vue-router` 和 `pinia`(或其他状态管理库):
```bash
npm install vue-router@4 pinia
```
#### 2. 创建路由配置文件 `router/index.ts`
```ts
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
import { useUserStore } from '@/stores/userStore'
const routes: Array<RouteRecordRaw> = [
{
path: '/login',
name: 'Login',
component: () => import('@/views/Login.vue')
},
{
path: '/dashboard',
name: 'Dashboard',
component: () => import('@/views/Dashboard.vue'),
meta: { requiresAuth: true }
},
{
path: '/profile',
name: 'Profile',
component: () => import('@/views/Profile.vue'),
beforeEnter: (to, from, next) => {
const userStore = useUserStore()
if (userStore.isAuthenticated) {
next()
} else {
next({ name: 'Login' })
}
}
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
router.beforeEach((to, from, next) => {
const userStore = useUserStore()
const isAuthenticated = userStore.isAuthenticated
if (to.meta.requiresAuth && !isAuthenticated) {
next({ name: 'Login' })
} else {
next()
}
})
export default router
```
#### 3. 创建用户状态管理模块 `stores/userStore.ts`
```ts
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
state: () => ({
isAuthenticated: false // 初始状态为未登录
}),
actions: {
login() {
this.isAuthenticated = true
},
logout() {
this.isAuthenticated = false
}
}
})
```
#### 4. 在组件中使用组件内守卫 `views/Profile.vue`
```vue
<template>
<div>用户个人资料页面</div>
</template>
<script setup lang="ts">
import { beforeRouteEnter } from 'vue-router'
import { useUserStore } from '@/stores/userStore'
const userStore = useUserStore()
beforeRouteEnter((to, from, next) => {
if (userStore.isAuthenticated) {
next()
} else {
next({ name: 'Login' })
}
})
</script>
```
通过上述方式,可以在 Vue 3 + TypeScript 项目中灵活实现路由守卫,确保应用的安全性和用户体验。
---