基础篇二 Nuxt4 路由守卫:页面访问控制

文章目录

有些页面不是谁都能访问的。后台管理只有管理员能进,个人中心需要登录才能看,会员内容要付费才能解锁......这些都是页面访问控制的场景。Nuxt 的中间件系统就是来解决这些问题的。

一、什么是路由守卫

路由守卫就是导航过程中的"关卡":

  1. 用户点击链接
  2. 触发路由守卫(关卡检查)
  3. 检查通过 → 放行
  4. 检查不通过 → 重定向或拦截

Nuxt 用中间件来实现路由守卫,比 Vue Router 的方式更简洁。

二、定义中间件

中间件放在 middleware 目录。创建一个登录检查中间件:

ts 复制代码
// middleware/auth.ts
export default defineNuxtRouteMiddleware((to, from) => {
  const token = useCookie('token')
  
  // 未登录,跳转到登录页
  if (!token.value) {
    return navigateTo('/login')
  }
})

在页面中使用:

vue 复制代码
<script setup lang="ts">
definePageMeta({
  middleware: 'auth'  // 使用 auth 中间件
})
</script>

<template>
  <div>
    <h1>个人中心</h1>
    <p>只有登录用户能看到</p>
  </div>
</template>

三、全局中间件

想让中间件对所有页面生效,文件名加 .global 后缀:

ts 复制代码
// middleware/auth.global.ts
export default defineNuxtRouteMiddleware((to, from) => {
  // 所有页面都会经过这里
  console.log('导航到:', to.path)
})

典型场景:全局登录状态检查

ts 复制代码
// middleware/auth.global.ts
export default defineNuxtRouteMiddleware((to, from) => {
  const token = useCookie('token')
  const publicPages = ['/', '/login', '/register']
  
  // 公开页面直接放行
  if (publicPages.includes(to.path)) {
    return
  }
  
  // 非公开页面需要登录
  if (!token.value) {
    return navigateTo('/login')
  }
})

四、多个中间件

页面可以同时使用多个中间件:

vue 复制代码
<script setup lang="ts">
definePageMeta({
  middleware: [
    'auth',      // 先检查登录
    'admin'      // 再检查管理员权限
  ]
})
</script>

中间件按数组顺序执行,任何一个返回重定向就会中断后续流程。

五、中间件传参

中间件可以接收参数:

ts 复制代码
// middleware/role.ts
export default defineNuxtRouteMiddleware((to, from) => {
  const requiredRole = to.meta.role as string
  const userRole = useCookie('role').value
  
  if (requiredRole && userRole !== requiredRole) {
    return navigateTo('/403')
  }
})

页面中定义需要的角色:

vue 复制代码
<script setup lang="ts">
definePageMeta({
  middleware: 'role',
  meta: {
    role: 'admin'  // 需要管理员角色
  }
})
</script>

六、重定向选项

navigateTo 支持多种选项:

ts 复制代码
// 外部链接
return navigateTo('https://google.com', { external: true })

// 替换历史记录
return navigateTo('/login', { replace: true })

// 新窗口打开
return navigateTo('/report', { open: { target: '_blank' } })

// 保留查询参数
return navigateTo({
  path: '/login',
  query: { redirect: to.fullPath }  // 登录后跳回原页面
})

七、中止导航

不是所有情况都要重定向,有时候只需要中止:

ts 复制代码
export default defineNuxtRouteMiddleware((to, from) => {
  const confirmed = confirm('确定要离开吗?未保存的内容会丢失')
  
  if (!confirmed) {
    return abortNavigation()  // 中止导航,留在当前页
  }
  
  // 返回 undefined 或不返回就是放行
})

还可以传递错误信息:

ts 复制代码
export default defineNuxtRouteMiddleware((to, from) => {
  return abortNavigation(
    createError({
      statusCode: 403,
      message: '您没有权限访问此页面'
    })
  )
})

八、页面离开确认

表单页面常用,防止用户误操作丢失数据:

ts 复制代码
// middleware/unsaved-changes.ts
export default defineNuxtRouteMiddleware((to, from) => {
  const hasUnsavedChanges = useState('unsavedChanges')
  
  if (hasUnsavedChanges.value) {
    const confirmed = confirm('有未保存的更改,确定要离开吗?')
    if (!confirmed) {
      return abortNavigation()
    }
    // 确认离开,重置状态
    hasUnsavedChanges.value = false
  }
})

页面中:

vue 复制代码
<script setup lang="ts">
const hasUnsavedChanges = useState('unsavedChanges')

// 表单数据变化时
watch(formData, () => {
  hasUnsavedChanges.value = true
}, { deep: true })

// 保存成功后
const save = async () => {
  await saveForm()
  hasUnsavedChanges.value = false
}

definePageMeta({
  middleware: 'unsaved-changes'
})
</script>

九、服务端中间件

中间件在 SSR 时也会执行。有些检查需要只在服务端进行:

ts 复制代码
export default defineNuxtRouteMiddleware(async (to, from) => {
  // 只在服务端执行
  if (process.server) {
    const event = useRequestEvent()
    const ip = getRequestIP(event)
    
    // IP 黑名单检查
    if (await isBlockedIP(ip)) {
      return navigateTo('/blocked')
    }
  }
})

十、中间件执行顺序

Nuxt 中间件执行顺序:

  1. 全局中间件(按字母排序)
  2. 页面定义的中间件(按定义顺序)
  3. 布局中间件(如果有)
ts 复制代码
// middleware/01-first.global.ts  - 先执行
// middleware/02-second.global.ts - 后执行

十一、调试中间件

开发时可以打印日志:

ts 复制代码
export default defineNuxtRouteMiddleware((to, from) => {
  console.log('From:', from.path)
  console.log('To:', to.path)
  console.log('Meta:', to.meta)
})

总结

路由守卫核心用法:

功能 实现方式
登录检查 middleware/auth.ts
全局守卫 文件名加 .global
多个守卫 middleware: ['auth', 'admin']
重定向 navigateTo('/path')
中止导航 abortNavigation()
传递错误 abortNavigation(createError(...))

路由守卫是权限控制的基础,下一篇我们聊聊组件进阶------插槽与事件传递。

相关文章

入门篇三:Nuxt4组件自动导入:写代码少敲一半字

入门篇二:Nuxt 4路由自动生成:告别手动配置路由的日子

延伸阅读

nuxt4完整系列,持续更新中。。,欢迎来逛逛


内容有帮助?点赞、收藏、关注三连!评论区等你 💪

相关推荐
weixin_408099677 分钟前
【完整教程】天诺脚本如何调用 OCR 文字识别 API?自动识别屏幕文字实战(附代码)
前端·人工智能·后端·ocr·api·天诺脚本·自动识别文字脚本
吴声子夜歌8 分钟前
ES6——Generator函数详解
前端·javascript·es6
吴声子夜歌9 分钟前
ES6——Set和Map详解
前端·javascript·es6
码喽7号39 分钟前
vue学习四:Axios网络请求
前端·vue.js·学习
粥里有勺糖1 小时前
视野修炼-技术周刊第129期 | 上一次古法编程是什么时候
前端·javascript·github
whuhewei2 小时前
JS获取CSS动画的旋转角度
前端·javascript·css
蓝黑20202 小时前
Vue组件通信之v-model
前端·javascript·vue
像素之间2 小时前
为什么运行时要加set NODE_OPTIONS=--openssl-legacy-provider && vue-cli-service serve
前端·javascript·vue.js
M ? A2 小时前
Vue转React实战:defineProps精准迁移实战
前端·javascript·vue.js·经验分享·react.js·开源·vureact
西陵2 小时前
别再写 Prompt 了Spec Mode 才是下一代 AI 编程范式
前端·人工智能·ai编程