pages
Vue Router
如果您只使用 app.vue
,它将不会被包含。要强制使用页面系统,请在 nuxt.config
中设置 pages: true
或拥有一个 router.options.ts
。使用
页面是 Vue 组件,可以拥有 Nuxt 支持的任何有效扩展名(默认情况下为 .vue
、.js
、.jsx
、.mjs
、.ts
或 .tsx
)。
Nuxt 将自动为您 ~/pages/
目录中的每个页面创建路由。
<template>
<h1>Index page</h1>
</template>
// https://vuejs.ac.cn/guide/extras/render-function.html
export default defineComponent({
render () {
return h('h1', 'Index page')
},
})
// https://nuxtjs.org.cn/docs/4.x/examples/advanced/jsx
// https://vuejs.ac.cn/guide/extras/render-function.html#jsx-tsx
export default defineComponent({
render () {
return <h1>Index page</h1>
},
})
app/pages/index.vue
文件将被映射到应用程序的 /
路由。
如果您正在使用 app.vue
,请确保使用 <NuxtPage/>
组件来显示当前页面。
<template>
<div>
<!-- Markup shared across all pages, ex: NavBar -->
<NuxtPage />
</div>
</template>
页面必须只有一个根元素,才能在页面之间实现路由过渡。HTML 注释也被视为元素。
这意味着当路由在服务器端渲染或静态生成时,您将能够正确看到其内容,但当您在客户端导航期间导航到该路由时,路由之间的过渡将失败,并且您会看到该路由将不会被渲染。
以下是一些示例,说明具有单个根元素的页面是什么样的
<template>
<div>
<!-- This page correctly has only one single root element -->
Page content
</div>
</template>
<template>
<!-- This page will not render when route changes during client side navigation, because of this comment -->
<div>Page content</div>
</template>
<template>
<div>This page</div>
<div>Has more than one root element</div>
<div>And will not render when route changes during client side navigation</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 访问路由,有一个全局的 useRoute
函数,它允许您像 Options API 中的 this.$route
一样访问路由。
<script setup lang="ts">
const route = useRoute()
if (route.params.group === 'admins' && !route.params.id) {
console.log('Warning! Make sure user is authenticated!')
}
</script>
/foo/hello
路由,~/pages/foo.vue
将优先于 ~/pages/foo/[slug].vue
。使用
~/pages/foo/index.vue
和 ~/pages/foo/[slug].vue
来匹配 /foo
和 /foo/hello
,并使用不同的页面。捕获所有路由
如果您需要一个包罗万象的路由,您可以通过使用名为 [...slug].vue
的文件来创建它。这将匹配该路径下的所有路由。
<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>
组件插入到 app/pages/parent.vue
中
<template>
<div>
<h1>I am the parent view</h1>
<NuxtPage :foobar="123" />
</div>
</template>
<script setup lang="ts">
const props = defineProps({
foobar: String,
})
console.log(props.foobar)
</script>
子路由键
如果您想对 <NuxtPage>
组件何时重新渲染(例如,用于过渡)进行更多控制,您可以通过 pageKey
prop 传递字符串或函数,或者通过 definePageMeta
定义 key
值
<template>
<div>
<h1>I am the parent view</h1>
<NuxtPage :page-key="route => route.fullPath" />
</div>
</template>
或者
<script setup lang="ts">
definePageMeta({
key: route => route.fullPath,
})
</script>
路由组
在某些情况下,您可能希望以不影响基于文件的路由的方式将一组路由分组。为此,您可以将文件放在用括号括起来的文件夹中——(
和 )
。
例如
-| pages/
---| index.vue
---| (marketing)/
-----| about.vue
-----| contact.vue
这将在你的应用中生成 /
、/about
和 /contact
页面。 marketing
组在 URL 结构中会被忽略。
页面元数据
您可能希望为应用程序中的每个路由定义元数据。您可以使用 definePageMeta
宏来完成此操作,它在 <script>
和 <script setup>
中都有效
<script setup lang="ts">
definePageMeta({
title: 'My home page',
})
</script>
然后可以通过 route.meta
对象在应用程序的其余部分访问此数据。
<script setup lang="ts">
const route = useRoute()
console.log(route.meta.title) // My home page
</script>
如果您正在使用嵌套路由,则所有这些路由的页面元数据将合并到一个对象中。有关路由元数据的更多信息,请参阅vue-router 文档.
与 defineEmits
或 defineProps
(参见Vue 文档)非常相似,definePageMeta
是一个编译器宏。它将被编译掉,因此您无法在组件中引用它。相反,传递给它的元数据将被提升到组件之外。因此,页面元对象不能引用组件。但是,它可以引用导入的绑定以及本地定义的纯函数。
<script setup lang="ts">
import { someData } from '~/utils/example'
function validateIdParam (route) {
return route.params.id && !Number.isNaN(Number(route.params.id))
}
const title = ref('')
definePageMeta({
validate: validateIdParam,
someData,
title, // do not do this, the ref will be hoisted out of the component
})
</script>
特殊元数据
当然,欢迎您在应用程序中定义自己的元数据。但是,使用 definePageMeta
定义的一些元数据具有特定用途
alias
您可以定义页面别名。它们允许您从不同的路径访问同一页面。它可以是字符串或字符串数组,如vue-router 文档中所定义.
keepalive
如果您在 definePageMeta
中设置了 keepalive: true
,Nuxt 会自动将您的页面包装在Vue <KeepAlive>
组件中。这可能很有用,例如,在具有动态子路由的父路由中,如果您想在路由更改时保留页面状态。
当您的目标是保留父路由的状态时,请使用以下语法:<NuxtPage keepalive />
。您还可以设置要传递给 <KeepAlive>
的 props(参见完整列表).
您可以在您的 nuxt.config
中为此属性设置默认值。
key
参见上方.
layout
您可以定义用于渲染路由的布局。它可以是 false(禁用任何布局),一个字符串或一个 ref/computed,如果您想以某种方式使其具有响应性。关于布局的更多信息。
layoutTransition
和 pageTransition
您可以为包装页面和布局的 <transition>
组件定义过渡属性,或者传入 false
来禁用该路由的 <transition>
包装器。您可以查看可以传递的选项列表或阅读更多关于过渡如何工作的信息.
您可以在您的 nuxt.config
中为此属性设置默认值。
middleware
您可以定义在加载此页面之前应用的中间件。它将与任何匹配的父/子路由中使用的所有其他中间件合并。它可以是字符串、函数(遵循全局前置守卫模式的匿名/内联中间件函数)或字符串/函数的数组。关于命名中间件的更多信息。
name
您可以为此页面的路由定义名称。
path
如果您有比文件名更复杂的模式,可以定义路径匹配器。请参阅vue-router
文档获取更多信息。
props
允许将路由 params
作为 props 传递给页面组件。请参阅vue-router
文档获取更多信息。
自定义元数据的类型化
如果您为页面添加了自定义元数据,您可能希望以类型安全的方式进行。可以增强 definePageMeta
接受的对象的类型
declare module '#app' {
interface PageMeta {
pageType?: string
}
}
// It is always important to ensure you import/export something when augmenting a type
export {}
导航
要在应用程序页面之间导航,您应该使用 <NuxtLink>
组件。
此组件已包含在 Nuxt 中,因此您无需像其他组件一样导入它。
指向 app/pages
文件夹中 index.vue
页面的简单链接
<template>
<NuxtLink to="/">Home page</NuxtLink>
</template>
编程式导航
Nuxt 允许通过 navigateTo()
实用方法进行编程导航。使用此实用方法,您将能够在应用程序中以编程方式导航用户。这对于获取用户输入并在整个应用程序中动态导航他们非常有用。在此示例中,我们有一个名为 navigate()
的简单方法,当用户提交搜索表单时会调用该方法。
await
navigateTo
或通过从函数返回来链式处理其结果。<script setup lang="ts">
const name = ref('')
const type = ref(1)
function navigate () {
return navigateTo({
path: '/search',
query: {
name: name.value,
type: type.value,
},
})
}
</script>
仅限客户端页面
您可以通过给页面添加 .client.vue
后缀将其定义为仅限客户端。此页面的任何内容都不会在服务器上渲染。
仅限服务器页面
您可以通过给页面添加 .server.vue
后缀将其定义为仅限服务器。虽然您可以使用客户端导航(由 vue-router
控制)导航到该页面,但它将自动使用服务器组件渲染,这意味着渲染该页面所需的代码将不会在您的客户端包中。
自定义路由
随着您的应用程序变得越来越大和复杂,您的路由可能需要更大的灵活性。为此,Nuxt 直接公开了路由器、路由和路由器选项,以便以不同的方式进行自定义。
多个页面目录
默认情况下,您的所有页面都应位于项目根目录下的一个 app/pages
目录中。
但是,您可以使用 Nuxt Layers 来创建应用程序页面的分组
-| some-app/
---| nuxt.config.ts
---| pages/
-----| app-page.vue
-| nuxt.config.ts
// some-app/nuxt.config.ts
export default defineNuxtConfig({
})
export default defineNuxtConfig({
extends: ['./some-app'],
})