Nuxt.js路由中间件 #
一、中间件概述 #
路由中间件是在导航到特定路由之前运行的函数,可以用于:
- 身份验证
- 权限检查
- 日志记录
- 重定向
- 数据预加载
二、创建中间件 #
2.1 匿名中间件 #
直接在页面中定义:
vue
<script setup lang="ts">
definePageMeta({
middleware: [
(to, from) => {
console.log('导航到:', to.path)
}
]
})
</script>
2.2 命名中间件 #
在 middleware/ 目录下创建:
middleware/auth.ts:
typescript
export default defineNuxtRouteMiddleware((to, from) => {
const isAuthenticated = useState('authenticated')
if (!isAuthenticated.value) {
return navigateTo('/login')
}
})
2.3 全局中间件 #
在文件名后添加 .global 后缀:
middleware/auth.global.ts:
typescript
export default defineNuxtRouteMiddleware((to, from) => {
console.log('全局中间件:', to.path)
})
全局中间件会在每次路由导航时自动执行。
三、使用中间件 #
3.1 单个中间件 #
vue
<script setup lang="ts">
definePageMeta({
middleware: 'auth'
})
</script>
3.2 多个中间件 #
vue
<script setup lang="ts">
definePageMeta({
middleware: ['auth', 'admin']
})
</script>
3.3 中间件执行顺序 #
- 全局中间件(按字母顺序)
- 页面定义的中间件(按数组顺序)
四、中间件参数 #
4.1 to和from对象 #
typescript
export default defineNuxtRouteMiddleware((to, from) => {
console.log('目标路由:', to.path)
console.log('来源路由:', from?.path)
console.log('路由参数:', to.params)
console.log('查询参数:', to.query)
console.log('路由元信息:', to.meta)
})
4.2 to对象属性 #
| 属性 | 说明 |
|---|---|
path |
路由路径 |
params |
路由参数 |
query |
查询参数 |
hash |
URL hash |
meta |
路由元信息 |
name |
路由名称 |
matched |
匹配的路由记录 |
五、中间件返回值 #
5.1 阻止导航 #
返回 navigateTo 重定向:
typescript
export default defineNuxtRouteMiddleware((to, from) => {
return navigateTo('/login')
})
5.2 带参数重定向 #
typescript
export default defineNuxtRouteMiddleware((to, from) => {
return navigateTo({
path: '/login',
query: {
redirect: to.fullPath
}
})
})
5.3 外部重定向 #
typescript
export default defineNuxtRouteMiddleware((to, from) => {
return navigateTo('https://example.com', {
external: true
})
})
5.4 抛出错误 #
typescript
export default defineNuxtRouteMiddleware((to, from) => {
throw createError({
statusCode: 403,
message: '没有访问权限'
})
})
5.5 放行导航 #
不返回任何值或返回 undefined:
typescript
export default defineNuxtRouteMiddleware((to, from) => {
// 验证通过,放行
})
六、常见中间件场景 #
6.1 身份验证中间件 #
middleware/auth.ts:
typescript
export default defineNuxtRouteMiddleware((to, from) => {
const { isAuthenticated } = useAuth()
if (!isAuthenticated.value) {
return navigateTo({
path: '/login',
query: { redirect: to.fullPath }
})
}
})
composables/useAuth.ts:
typescript
export const useAuth = () => {
const user = useState('user', () => null)
const token = useCookie('token')
const isAuthenticated = computed(() => !!token.value && !!user.value)
const login = async (credentials: { email: string; password: string }) => {
const { data } = await useFetch('/api/auth/login', {
method: 'POST',
body: credentials
})
if (data.value) {
user.value = data.value.user
token.value = data.value.token
}
}
const logout = async () => {
await useFetch('/api/auth/logout')
user.value = null
token.value = null
}
return {
user,
token,
isAuthenticated,
login,
logout
}
}
6.2 角色权限中间件 #
middleware/admin.ts:
typescript
export default defineNuxtRouteMiddleware((to, from) => {
const { user } = useAuth()
if (user.value?.role !== 'admin') {
throw createError({
statusCode: 403,
message: '需要管理员权限'
})
}
})
使用:
vue
<script setup lang="ts">
definePageMeta({
middleware: ['auth', 'admin']
})
</script>
6.3 日志中间件 #
middleware/logger.global.ts:
typescript
export default defineNuxtRouteMiddleware((to, from) => {
console.log(`[${new Date().toISOString()}] ${from?.path} → ${to.path}`)
})
6.4 维护模式中间件 #
middleware/maintenance.global.ts:
typescript
export default defineNuxtRouteMiddleware((to, from) => {
const config = useRuntimeConfig()
if (config.public.maintenanceMode && to.path !== '/maintenance') {
return navigateTo('/maintenance')
}
})
6.5 语言检测中间件 #
middleware/i18n.global.ts:
typescript
export default defineNuxtRouteMiddleware((to, from) => {
const { locale, setLocale } = useI18n()
const savedLocale = useCookie('locale')
if (savedLocale.value && savedLocale.value !== locale.value) {
setLocale(savedLocale.value)
}
})
七、中间件与路由元信息 #
7.1 定义元信息 #
vue
<script setup lang="ts">
definePageMeta({
middleware: 'auth',
meta: {
requiresAuth: true,
roles: ['admin', 'editor']
}
})
</script>
7.2 在中间件中访问元信息 #
typescript
export default defineNuxtRouteMiddleware((to, from) => {
const { user } = useAuth()
if (to.meta.requiresAuth && !user.value) {
return navigateTo('/login')
}
const requiredRoles = to.meta.roles as string[] | undefined
if (requiredRoles && !requiredRoles.includes(user.value?.role)) {
throw createError({
statusCode: 403,
message: '权限不足'
})
}
})
八、中间件最佳实践 #
8.1 组合中间件 #
创建可复用的中间件组合:
middleware/combined.ts:
typescript
export default defineNuxtRouteMiddleware(async (to, from) => {
const authResult = await authMiddleware(to, from)
if (authResult) return authResult
const roleResult = await roleMiddleware(to, from)
if (roleResult) return roleResult
})
async function authMiddleware(to, from) {
const { isAuthenticated } = useAuth()
if (!isAuthenticated.value) {
return navigateTo('/login')
}
}
async function roleMiddleware(to, from) {
const { user } = useAuth()
const requiredRoles = to.meta.roles as string[] | undefined
if (requiredRoles && !requiredRoles.includes(user.value?.role)) {
throw createError({ statusCode: 403 })
}
}
8.2 条件执行 #
typescript
export default defineNuxtRouteMiddleware((to, from) => {
if (import.meta.client) {
// 仅在客户端执行
}
if (import.meta.server) {
// 仅在服务端执行
}
})
8.3 异步操作 #
typescript
export default defineNuxtRouteMiddleware(async (to, from) => {
const { data } = await useFetch('/api/check-permission', {
query: { path: to.path }
})
if (!data.value?.allowed) {
return navigateTo('/forbidden')
}
})
九、调试中间件 #
9.1 开发模式日志 #
typescript
export default defineNuxtRouteMiddleware((to, from) => {
if (process.dev) {
console.group('中间件执行')
console.log('目标:', to.path)
console.log('来源:', from?.path)
console.log('参数:', to.params)
console.groupEnd()
}
})
9.2 使用DevTools #
Nuxt DevTools 可以查看中间件执行情况。
十、完整示例 #
10.1 完整认证系统 #
middleware/auth.ts:
typescript
export default defineNuxtRouteMiddleware((to, from) => {
const { isAuthenticated, user } = useAuth()
const token = useCookie('token')
if (!token.value) {
return navigateTo({
path: '/login',
query: { redirect: to.fullPath }
})
}
if (!user.value) {
return navigateTo({
path: '/login',
query: { redirect: to.fullPath }
})
}
const requiredRoles = to.meta.roles as string[] | undefined
if (requiredRoles && !requiredRoles.includes(user.value.role)) {
throw createError({
statusCode: 403,
message: '您没有访问此页面的权限'
})
}
})
pages/admin/index.vue:
vue
<script setup lang="ts">
definePageMeta({
middleware: 'auth',
meta: {
roles: ['admin']
}
})
</script>
<template>
<div>
<h1>管理后台</h1>
</div>
</template>
十一、总结 #
本章介绍了 Nuxt.js 路由中间件:
- 创建命名中间件和全局中间件
- 使用
navigateTo进行重定向 - 实现身份验证和权限控制
- 结合路由元信息进行灵活控制
- 中间件的最佳实践
中间件是构建安全、可控应用的重要工具,下一章我们将学习路由守卫。
最后更新:2026-03-28