路由

Nuxt 的文件系统路由会为 pages/ 目录中的每个文件创建一个路由。

Nuxt 的核心功能之一是文件系统路由器。pages/ 目录中的每个 Vue 文件都会创建一个对应的 URL(或路由),用于展示该文件的内容。通过为每个页面使用动态导入,Nuxt 利用代码分割技术,只为请求的路由加载最少的 JavaScript。

页面

Nuxt 路由基于 vue-router 构建,会根据 pages/ 目录 中创建的每个组件的文件名生成路由。

这种文件系统路由采用命名约定来创建动态路由和嵌套路由:

-| pages/
---| about.vue
---| index.vue
---| posts/
-----| [id].vue
阅读更多 Docs > Guide > Directory Structure > Pages.

导航

<NuxtLink> 组件用于在页面之间进行链接。它会渲染一个 <a> 标签,其 href 属性设置为目标页面的路由。应用程序激活后,页面切换通过 JavaScript 完成,同时更新浏览器的 URL。这避免了整页刷新,并支持动画过渡效果。

<NuxtLink> 进入客户端的视口时,Nuxt 会自动预加载链接页面的组件和有效载荷(生成的页面),从而实现更快的导航。

pages/app.vue
<template>
  <header>
    <nav>
      <ul>
        <li><NuxtLink to="/about">关于</NuxtLink></li>
        <li><NuxtLink to="/posts/1">文章 1</NuxtLink></li>
        <li><NuxtLink to="/posts/2">文章 2</NuxtLink></li>
      </ul>
    </nav>
  </header>
</template>
阅读更多 Docs > API > Components > Nuxt Link.

路由参数

在 Vue 组件的 <script setup> 块或 setup() 方法中,可以使用 useRoute() 组合式 API 来访问当前路由的详细信息。

pages/posts/[id].vue
<script setup lang="ts">
const route = useRoute()

// 访问 /posts/1 时,route.params.id 的值为 1
console.log(route.params.id)
</script>
阅读更多 Docs > API > Composables > Use Route.

路由中间件

Nuxt 提供了一个可自定义的路由中间件框架,你可以在整个应用中使用它,非常适合提取那些需要在导航到特定路由之前运行的代码。

路由中间件在 Nuxt 应用的 Vue 部分运行。尽管名称相似,但它们与服务器中间件完全不同,服务器中间件在应用的 Nitro 服务器部分运行。

路由中间件有三种类型:

  1. 匿名(或内联)路由中间件,直接定义在使用它们的页面中。
  2. 命名路由中间件,放置在 middleware/ 目录中,当在页面上使用时,会通过异步导入自动加载。(注意:路由中间件的名称会规范化为短横线命名法,因此 someMiddleware 会变为 some-middleware。)
  3. 全局路由中间件,放置在 middleware/ 目录中(带有 .global 后缀),会在每次路由变化时自动运行。

以下是保护 /dashboard 页面的 auth 中间件示例:

export default defineNuxtRouteMiddleware((to, from) => {
  // isAuthenticated() 是一个示例方法,用于验证用户是否已认证
  if (isAuthenticated() === false) {
    return navigateTo('/login')
  }
})
阅读更多 Docs > Guide > Directory Structure > Middleware.

路由验证

Nuxt 通过每个需要验证的页面中 definePageMeta() 里的 validate 属性提供路由验证功能。

validate 属性接收 route 作为参数。你可以返回一个布尔值来确定这是否是一个可以用当前页面渲染的有效路由。如果返回 false,将导致 404 错误。你也可以直接返回一个包含 statusCode/statusMessage 的对象来自定义返回的错误。

如果有更复杂的使用场景,你可以改用匿名路由中间件。

pages/posts/[id].vue
<script setup lang="ts">
definePageMeta({
  validate: async (route) => {
    // 检查 id 是否由数字组成
    return typeof route.params.id === 'string' && /^\d+$/.test(route.params.id)
  }
})
</script>
阅读更多 Docs > API > Utils > Define Page Meta.