戏里戏外

Nuxt 3 路由守卫:使用中间件实现路由控制

2024-11-13#Nuxt

Nuxt 3 提供了一个强大而灵活的路由守卫机制。

无论是简单的认证检查,还是复杂的权限控制,都可以优雅地实现。

合理使用这些特性,可以让你的应用更安全、更易维护。

什么是路由守卫?

路由守卫是 Web 开发中控制路由访问的重要机制,主要用于:

  • 需要认证的路由保护

  • 基于用户角色的路由重定向

  • 在页面跳转前执行特定逻辑(如数据预加载)

Nuxt 3 中的路由守卫实现方式

在 Nuxt 3 中可以通过 defineNuxtRouteMiddleware 来实现路由守卫,主要有三种方式:

1. 内联路由中间件

// pages/dashboard.vue
<script setup lang="ts">
const { user } = useAuth()

definePageMeta({
  middleware: [
    function (to, from) {
      const isAdmin = user.value?.role
      if (!isAdmin) {
        return navigateTo('/')
      }
    }
  ]
})
</script>

2. 命名路由中间件

// middleware/admin-guard.ts
export default defineNuxtRouteMiddleware((to, from) => {
  const isAdmin = false // 可以从 composable 或工具函数获取

  if (!isAdmin) {
    return navigateTo('/')
  }
})

使用方式:

// pages/dashboard.vue
<script setup lang="ts">
definePageMeta({
  middleware: ["admin-guard"]
})
</script>

3. 全局路由中间件

// middleware/auth.global.ts
export default defineNuxtRouteMiddleware((to, from) => {
  const { user } = useAuthState()
  const isLoggedIn = user.value

  if (!isLoggedIn && to.path !== '/login') {
    return navigateTo('/login')
  }
})

中间件执行顺序

中间件的执行遵循以下顺序:

  1. 全局中间件(按文件名字母顺序)
  2. 页面特定中间件

自定义全局中间件顺序

可以通过文件名前缀来控制执行顺序:

middleware/

├── 01.initialize.global.ts
├── 02.auth.global.ts
└── 03.track.global.ts

异步路由守卫

支持在中间件中使用异步操作:

export default defineNuxtRouteMiddleware(async (to, from) => {
  const user = await getUserFromApi()

  if (!user?.isAuthenticated) {
    return navigateTo('/login')
  }
})
最佳实践
  1. 保持中间件简单

    • 每个中间件只关注一个功能
    • 复杂逻辑应拆分为多个中间件
  2. 使用 Composables 共享逻辑

    // composables/useAuthState.ts
    export const useAuthState = () => {
    	const isLoggedIn = ref(false)
    	return { isLoggedIn }
    }
    
  3. 避免阻塞导航

    • 避免在全局中间件中放置重量级逻辑
    • 优先使用 Pinia store 存储数据