Nuxt 提供了基于文件的路由机制,使用 Vue Router 技术来创建 Web 应用程序中的路由。
这种路由机制可以通过在项目中创建具有特定命名约定的文件来定义路由。
例如,在 pages 目录下创建一个名为 about.vue
的文件,将会自动创建一个路由,可以通过访问 /about 地址来访问该路由。
Nuxt 会自动根据文件名创建相应的路由,并将这些路由集成到 Vue Router 中。
这种基于文件的路由机制可以帮助开发人员更快地创建和维护路由,同时也可以提高应用程序的可读性和可维护性。
这个目录是可选的,这意味着如果你只使用 app.vue(除非你在 nuxt.config
中设置 pages: true
或者有一个 app/router.options.ts
),减少你的 应用程序的包大小。
使用方法
页面是 Vue 组件,可以具有 Nuxt 支持的任何 有效扩展名(默认为 .vue
、.js
、 .jsx
、.mjs
、.ts
或 .tsx
)。
Nuxt 会自动为你的 ~/pages/ 目录中的每个页面创建一个路由。
<template>
<h1>Index page</h1>
</template>
pages/index.vue
文件将映射到应用程序的 /
路由。
如果您使用的是 app.vue,请确保使用 <NuxtPage/>
组件来显示当前页面:
<template>
<div>
<!-- 跨所有页面共享的组件,例如:NavBar -->
<NuxtPage />
</div>
</template>
Nuxt 要求每个页面必须只有一个根元素,以便在不同页面之间进行路由切换时能够成功地进行过渡效果。这是因为在服务端渲染或静态生成时,Nuxt 可以正确地渲染该页面的内容。
但是当在客户端进行导航时,如果页面有多个根元素,那么路由之间的切换过渡效果将会失败,导致该路由页面不能正常渲染。
举例来说,以下是一个只有一个根元素的页面示例:
<template>
<div>
<!-- 此页面正确地只有一个根元素 -->
Page content
</div>
</template>
动态路由
如果您将任何内容放在方括号内,它将变成一个 动态路由 参数。
您可以在一个文件名或目录中混合和匹配多个参数,甚至是非动态文本。
如果您希望参数是 可选,则必须将其括在双方括号中 - 例如,~/pages/[[slug]]/index.vue
或 ~/pages/[[slug]].vue
将同时匹配 /
和 /test
。
示例
-| pages/
---| index.vue
---| users-[group]/
-----| [id].vue
在上面的示例中,您可以通过 $route
对象访问组件中的 group/id:
<template>
<p>{{ $route.params.group }} - {{ $route.params.id }}</p>
</template>
导航到/users-admins/123
将呈现:
<p>admins - 123</p>
如果你想在 Composition API 中访问路由信息,Nuxt 提供了一个全局的 useRoute()
函数。
该函数允许你像在 Options API 中使用 this.$route
一样来访问路由信息。
使用 useRoute()
函数可以在组件中方便地获取当前路由的信息,包括路由参数、查询参数、路径等。
<script setup>
const route = useRoute()
if (route.params.group === 'admins' && !route.params.id)
console.log('Warning! Make sure user is authenticated!')
</script>
捕获全部路由
如果你需要创建一个捕获所有路由的路由规则,可以创建一个文件并将其命名为 ...slug.vue。
这个文件将匹配该路径下的所有路由,无论这些路由是多少层级的嵌套。
...slug 语法表示一个动态路由参数,可以匹配任意数量的 URL 片段,而且这个参数的值将作为组件的 props 传递给该组件。
使用这个语法可以方便地处理动态路由,例如处理博客文章页面的路由,或者处理类似于 /products/12345
这样的商品详情页的路由。
<template>
<p>{{ $route.params.slug }}</p>
</template>
导航到/hello/world
将呈现:
<p>["hello", "world"]</p>
嵌套的路由
可以使用 <NuxtPage>
显示嵌套路由。
-| pages/
---| parent/
------| child.vue
---| parent.vue
此文件树将生成这些路由:
[
{
path: '/parent',
component: '~/pages/parent.vue',
name: 'parent',
children: [
{
path: 'child',
component: '~/pages/parent/child.vue',
name: 'parent-child'
}
]
}
]
要显示 child.vue
组件,您必须将 <NuxtPage>
组件插入到 pages/parent.vue
中:
<template>
<div>
<h1>I am the parent view</h1>
<NuxtPage :foobar="123" />
</div>
</template>
子路由键
如果你需要更多的控制来重新渲染 pageKey
属性传递字符串或函数,或者通过 definePageMeta
定义一个 key 值:
<template>
<div>
<h1>我是父级视图</h1>
<NuxtPage :page-key="someKey" />
</div>
</template>
或者,还可以:
<script setup>
definePageMeta({
key: route => route.fullPath
})
</script>
页面元数据
您可能想要为应用程序中的每个路由定义元数据。 您可以使用 definePageMeta
宏来执行此操作,该宏将在 <script>
和 <script setup>
中工作:
<script setup>
definePageMeta({
title: 'My home page'
})
</script>
然后可以通过route.meta
对象在应用程序的其余部分访问此数据。
<script setup>
const route = useRoute()
console.log(route.meta.title) // My home page
</script>
如果您使用嵌套路由,所有这些路由的页面元数据将合并到一个对象中。 有关路由元的更多信息,请参阅 vue-router 文档。
与 defineEmits
或 defineProps
类似(参见 Vue 文档),definePageMeta
是一个编译器宏。
它将被编译掉,因此你不能在组件内部引用它。相反,传递给它的元数据将被提升到组件外部。因此,页面元数据对象不能引用组件本身(或组件上定义的值)。但是,它可以引用导入的绑定。
<script setup>
import { someData } from '~/utils/example'
const title = ref('')
definePageMeta({
title, // 这会产生一个错误
someData
})
</script>
特殊元数据
当然,欢迎您定义元数据供您在整个应用程序中使用。 但是用 definePageMeta
定义的一些元数据有特殊用途:
alias
您可以定义页面别名。 它们允许您从不同的路径访问同一页面。 它可以是 vue-router 文档中 此处 定义的字符串或字符串数组。
keepalive
Nuxt 会自动将你的页面包装在 Vue <KeepAlive>
组件 如果你设置了 keepalive: true
definePageMeta
。 这可能很有用,例如,在具有动态子路由的父路由中,如果您想在路由更改期间保留页面状态。
当您的目标是保留父路由的状态时,请使用此语法:<NuxtPage keepalive />
。 您还可以设置要传递给 <KeepAlive>
的道具(请在 此处 查看完整列表)。
您可以 在您的 nuxt.config
中 为该属性设置一个默认值。
key
layout
你可以定义用于渲染路由的布局。如果你想使其响应式,则可以将其设置为 false(禁用任何布局)、字符串或引用/计算。关于布局的更多信息,请参阅文档中关于布局的内容。
layoutTransition & pageTransition
你可以为包裹在你的页面和布局中的<transition>
组件定义过渡属性,或者将false传递给该路由以禁用<transition>
包装器。你可以在此处查看可以传递的选项列表,或者阅读有关如何使用过渡的更多信息。具体而言,你可以自定义在页面切换时触发的动画、动画持续时间和延迟时间等属性。或阅读更多关于转换如何工作的信息
你可以在 nuxt.config.js
文件中设置默认的页面布局和过渡属性。具体可以参考nuxt.config
。
middleware
您可以在加载此页面之前定义要应用的中间件。 它将与任何匹配的父/子路由中使用的所有其他中间件合并。
它可以是一个字符串,一个函数(一个匿名/内联的中间件函数,遵循 全局前保护模式), 或字符串/函数数组。 更多关于命名中间件。
name
您可以为此页面的路由定义一个名称。
path
如果你有一个比文件名更复杂的模式,你可以定义一个路径匹配器。 有关详细信息,请参阅 vue-router
文档。
输入自定义元数据
如果您为页面添加自定义元数据,您可能希望以类型安全的方式进行。 可以增加 definePageMeta
接受的对象类型:
declare module '#app' {
interface PageMeta {
pageType?: string
}
}
// 确保在扩充类型时导入/导出某些内容始终很重要
export {}
导航链接
要在应用的页面之间导航,您应该使用 <NuxtLink>
组件。
该组件包含在 Nuxt 中,因此您不必像导入其他组件那样导入它。
指向 pages
文件夹中的 index.vue
页面的简单链接:
<template>
<NuxtLink to="/">Home page</NuxtLink>
</template>
详细了解 <NuxtLink>
用法。
编程式导航
Nuxt 3 允许通过navigateTo()
实用程序方法进行编程导航。 使用此实用程序方法,您将能够以编程方式在您的应用程序中导航用户。
这对于从用户那里获取输入并在整个应用程序中动态导航它们非常有用。
在此示例中,我们有一个名为navigate()
的简单方法,该方法在用户提交搜索表单时被调用。
注意: 确保始终在 navigateTo
上进行 await
或通过从函数返回来链接其结果。
<script setup>
const name = ref('')
const type = ref(1)
function navigate() {
return navigateTo({
path: '/search',
query: {
name: name.value,
type: type.value
}
})
}
</script>
自定义路由
随着您的应用变得越来越大和越来越复杂,您的路由可能需要更大的灵活性。 为此,Nuxt 直接暴露了 router、routes 和 router 选项,以不同的方式进行定制。