路由 Routing

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

Nuxt 的一项核心功能是文件系统路由器。 pages/ 目录中的每个 Vue 文件都会创建一个相应的 URL(或路由)来显示文件的内容。 通过对每个页面使用动态导入,Nuxt 利用代码拆分为请求的路由发送最少数量的 JavaScript。

页面

Nuxt 路由基于 vue-router 并从 pages/ 目录中创建的每个组件生成路由, 基于他们的文件名。

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

页面/目录
pages/
--| about.vue
--| index.vue
--| posts/
----| [id].vue

导航

<NuxtLink> 组件链接它们之间的页面。 它呈现一个 <a> 标签,其中 href 属性设置为页面的路由。 应用程序混合后,页面转换将通过更新浏览器 URL 在 JavaScript 中执行。 这可以防止整页刷新并允许动画过渡。

进入客户端视口时,Nuxt 会提前自动预取链接页面的组件和有效负载(生成的页面),从而加快导航速度。

pages/app.vue
vue
<template>
  <header>
    <nav>
      <ul>
        <li>
          <NuxtLink to="/about">
            About
          </NuxtLink>
        </li>
        <li>
          <NuxtLink to="/posts/1">
            Post 1
          </NuxtLink>
        </li>
        <li>
          <NuxtLink to="/posts/2">
            Post 2
          </NuxtLink>
        </li>
      </ul>
    </nav>
  </header>
</template>

路由参数

useRoute() 可组合项可用于 <script setup> 块或 Vue 组件的 setup() 方法中以访问当前路线详细信息。

pages/posts/[id
vue
<script setup>
const route = useRoute()

// 当访问 /posts/1 时,route.params.id 将为 1
console.log(route.params.id)
</script>

路由中间件

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

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

路由中间件分为三种:

  1. 匿名(或内联)路由中间件,在使用它们的页面中直接定义。
  2. 具名路由中间件,放置在middleware/目录下,在页面使用时会异步导入自动加载。 (注意:路由中间件名称被标准化为 kebab-case,所以 someMiddleware 变成了 some-middleware。)
  3. 全局路由中间件,放置在middleware/目录下(后缀为.global),每次路由变化时自动运行。

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

ts
middleware/auth.ts
ts
export default defineNuxtRouteMiddleware((to, from) => {
  // isAuthenticated() 是验证用户是否通过身份验证的示例方法
  if (isAuthenticated() === false)
    return navigateTo('/login')
})

路由验证

Nuxt 通过您希望验证的每个页面的 definePageMeta 中的 validate 属性提供路由验证。

validate 属性接受 route 作为参数。 您可以返回一个布尔值来确定这是否是要使用此页面呈现的有效路由。

如果您返回 false,并且找不到另一个匹配项,则会导致 404 错误。 您也可以直接返回一个带有 statusCode/statusMessage 的对象,以立即响应错误(不会检查其他匹配项)。

如果您有更复杂的用例,那么您可以改用匿名路由中间件。

pages/posts/[id
vue
<script setup>
definePageMeta({
  validate: async (route) => {
    // 检查id是否由数字组成
    return /^\d+$/.test(route.params.id)
  }
})
</script>