pages
app.vue
,则不会包含 vue-router
。要强制使用页面系统,请在 nuxt.config
中设置 pages: true
或使用 app/router.options.ts
。用法
¥Usage
页面是 Vue 组件,可以包含 Nuxt 支持的任何 有效扩展名(默认为 .vue
、.js
、.jsx
、.mjs
、.ts
或 .tsx
)。
¥Pages are Vue components and can have any valid extension that Nuxt supports (by default .vue
, .js
, .jsx
, .mjs
, .ts
or .tsx
).
Nuxt 将自动为你的 ~/pages/
目录中的每个页面创建路由。
¥Nuxt will automatically create a route for every page in your ~/pages/
directory.
<template>
<h1>Index page</h1>
</template>
// https://vuejs.org/guide/extras/render-function.html
export default defineComponent({
render () {
return h('h1', 'Index page')
}
})
// https://nuxt.nodejs.cn/docs/examples/advanced/jsx
// https://vuejs.org/guide/extras/render-function.html#jsx-tsx
export default defineComponent({
render () {
return <h1>Index page</h1>
}
})
pages/index.vue
文件将映射到应用的 /
路由。
¥The pages/index.vue
file will be mapped to the /
route of your application.
如果你使用 app.vue
,请确保使用 <NuxtPage/>
组件显示当前页面:
¥If you are using app.vue
, make sure to use the <NuxtPage/>
component to display the current page:
<template>
<div>
<!-- Markup shared across all pages, ex: NavBar -->
<NuxtPage />
</div>
</template>
页面必须有一个根元素才能允许页面之间使用 路由转换。处理文件名可以添加 、、、 等后缀。
¥Pages must have a single root element to allow route transitions between pages. HTML comments are considered elements as well.
这意味着当路由是服务器渲染或静态生成时,你将能够正确看到其内容,但是当你在客户端导航期间导航到该路由时,路由之间的转换将失败,并且你将看到该路由不会被渲染。
¥This means that when the route is server-rendered, or statically generated, you will be able to see its contents correctly, but when you navigate towards that route during client-side navigation the transition between routes will fail and you'll see that the route will not be rendered.
以下是一些示例,用于说明包含单个根元素的页面是什么样的:
¥Here are some examples to illustrate what a page with a single root element looks like:
<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>
动态路由
¥Dynamic Routes
如果将任何内容放在方括号内,它将转换为 动态路由 参数。你可以在文件名或目录中混合搭配多个参数,甚至非动态文本。
¥If you place anything within square brackets, it will be turned into a dynamic route parameter. You can mix and match multiple parameters and even non-dynamic text within a file name or directory.
如果你希望参数为可选参数,则必须将其括在双方括号中。 - 例如,~/pages/[[slug]]/index.vue
或 ~/pages/[[slug]].vue
将同时匹配 /
和 /test
。
¥If you want a parameter to be optional, you must enclose it in double square brackets - for example, ~/pages/[[slug]]/index.vue
or ~/pages/[[slug]].vue
will match both /
and /test
.
-| pages/
---| index.vue
---| users-[group]/
-----| [id].vue
将 $route
作为参数传递给 是可选的,但建议传递它,以便在运行时让 覆盖服务器路由的运行时配置。
¥Given the example above, you can access group/id within your component via the $route
object:
<template>
<p>{{ $route.params.group }} - {{ $route.params.id }}</p>
</template>
导航到 /users-admins/123
将呈现:
¥Navigating to /users-admins/123
would render:
<p>admins - 123</p>
如果你想使用 Composition API 访问路由,可以使用全局函数 useRoute
,它允许你像 Options API 中的 this.$route
一样访问路由。
¥If you want to access the route using Composition API, there is a global useRoute
function that will allow you to access the route just like this.$route
in the Options API.
<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
。:br 使用 ~/pages/foo/index.vue
和 ~/pages/foo/[slug].vue
将 /foo
和 /foo/hello
与不同的页面匹配。Catch-all 路由
¥Catch-all Route
如果你需要一个 catch-all 路由,你可以使用名为 [...slug].vue
的文件来创建它。这将匹配该路径下的所有路由。
¥If you need a catch-all route, you create it by using a file named like [...slug].vue
. This will match all routes under that path.
<template>
<p>{{ $route.params.slug }}</p>
</template>
导航到 /hello/world
将呈现:
¥Navigating to /hello/world
would render:
<p>["hello", "world"]</p>
嵌套路由
¥Nested Routes
可以使用 <NuxtPage>
显示 嵌套路由。
¥It is possible to display nested routes with <NuxtPage>
.
示例:
¥Example:
-| pages/
---| parent/
-----| child.vue
---| parent.vue
此文件树将生成以下路由:
¥This file tree will generate these routes:
[
{
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
中:
¥To display the child.vue
component, you have to insert the <NuxtPage>
component inside 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'])
console.log(props.foobar)
</script>
子路由键
¥Child Route Keys
如果你希望更好地控制 <NuxtPage>
组件的重新渲染时间(例如,用于过渡),你可以通过 pageKey
属性传递字符串或函数,或者你可以通过 definePageMeta
定义一个 key
值:
¥If you want more control over when the <NuxtPage>
component is re-rendered (for example, for transitions), you can either pass a string or function via the pageKey
prop, or you can define a key
value via definePageMeta
:
<template>
<div>
<h1>I am the parent view</h1>
<NuxtPage :page-key="route => route.fullPath" />
</div>
</template>
或者:
¥Or alternatively:
<script setup lang="ts">
definePageMeta({
key: route => route.fullPath
})
</script>
路由组
¥Route Groups
在某些情况下,你可能希望将一组路由组合在一起,但又不影响基于文件的路由。因此,Nuxt 直接公开了路由、路由和路由选项,以便以不同的方式进行自定义。 - (
和 )
。
¥In some cases, you may want to group a set of routes together in a way which doesn't affect file-based routing. For this purpose, you can put files in a folder which is wrapped in parentheses - (
and )
.
例如:
¥For example:
-| pages/
---| index.vue
---| (marketing)/
-----| about.vue
-----| contact.vue
这将在你的应用中生成 /
、/about
和 /contact
页面。出于 URL 结构的原因,marketing
组会被忽略。
¥This will produce /
, /about
and /contact
pages in your app. The marketing
group is ignored for purposes of your URL structure.
页面元数据
¥Page Metadata
你可能需要为应用中的每条路由定义元数据。你可以使用 definePageMeta
宏来实现此操作,该宏在 <script>
和 <script setup>
中均可使用:
¥You might want to define metadata for each route in your app. You can do this using the definePageMeta
macro, which will work both in <script>
and in <script setup>
:
<script setup lang="ts">
definePageMeta({
title: 'My home page'
})
</script>
然后,你可以通过 route.meta
对象在应用的其余部分访问这些数据。
¥This data can then be accessed throughout the rest of your app from the route.meta
object.
<script setup lang="ts">
const route = useRoute()
console.log(route.meta.title) // My home page
</script>
如果你使用嵌套路由,则所有这些路由的页面元数据将合并为一个对象。对于大多数插件,默认的 vue-router 文档 或 就足够了。
¥If you are using nested routes, the page metadata from all these routes will be merged into a single object. For more on route meta, see the vue-router docs.
与 defineEmits
或 defineProps
(参见 Vue 文档)非常相似,definePageMeta
是一个编译器宏。它将被编译掉,因此你无法在组件中引用它。传递给它的元数据将被提升出组件。因此,页面元对象无法引用该组件。但是,它可以引用导入的绑定,以及本地定义的纯函数。
¥Much like defineEmits
or defineProps
(see Vue docs), definePageMeta
is a compiler macro. It will be compiled away so you cannot reference it within your component. Instead, the metadata passed to it will be hoisted out of the component.
Therefore, the page meta object cannot reference the component. However, it can reference imported bindings, as well as locally defined pure functions.
<script setup lang="ts">
import { someData } from '~/utils/example'
function validateIdParam(route) {
return route.params.id && !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>
特殊元数据
¥Special Metadata
当然,欢迎你在整个应用中自行定义元数据。但使用 definePageMeta
定义的某些元数据有特殊用途:
¥Of course, you are welcome to define metadata for your own use throughout your app. But some metadata defined with definePageMeta
has a particular purpose:
alias
你可以定义页面别名。它们允许你从不同的路径访问同一页面。它可以是字符串,也可以是字符串数组,如 vue-router 文档中 此处 的定义。
¥You can define page aliases. They allow you to access the same page from different paths. It can be either a string or an array of strings as defined here on vue-router documentation.
keepalive
如果你在 definePageMeta
中设置了 keepalive: true
,Nuxt 将自动将你的页面封装在 Vue <KeepAlive>
组件 中。例如,如果你想在路由更改期间保留页面状态,则在具有动态子路由的父路由中执行此操作可能很有用。
¥Nuxt will automatically wrap your page in the Vue <KeepAlive>
component if you set keepalive: true
in your definePageMeta
. This might be useful to do, for example, in a parent route that has dynamic child routes, if you want to preserve page state across route changes.
如果你的目标是保存父路由的状态,请使用以下语法:<NuxtPage keepalive />
。你还可以设置要传递给 <KeepAlive>
的 props(请参阅完整列表 此处)。
¥When your goal is to preserve state for parent routes use this syntax: <NuxtPage keepalive />
. You can also set props to be passed to <KeepAlive>
(see a full list here).
你可以为此属性 在你的 nuxt.config
中 设置默认值。
¥You can set a default value for this property in your nuxt.config
.
key
参见上文。
layout
你可以定义用于渲染路由的布局。如果你想以某种方式使其具有响应性,它可以是 false(禁用任何布局)、字符串或 ref/computed。更多关于布局。
¥You can define the layout used to render the route. This can be either false (to disable any layout), a string or a ref/computed, if you want to make it reactive in some way. More about layouts.
layoutTransition
和 pageTransition
¥layoutTransition
and pageTransition
你可以为封装页面和布局的 <transition>
组件定义过渡属性,或者传递 false
来禁用该路由的 <transition>
封装器。你可以查看可以传递给 此处 或读取 更多关于过渡如何工作的信息 的选项列表。
¥You can define transition properties for the <transition>
component that wraps your pages and layouts, or pass false
to disable the <transition>
wrapper for that route. You can see a list of options that can be passed here or read more about how transitions work.
你可以为这些属性 在你的 nuxt.config
中 设置默认值。
¥You can set default values for these properties in your nuxt.config
.
middleware
你可以定义在加载此页面之前要应用的中间件。它将与所有匹配的父/子路由中使用的其他中间件合并。它可以是字符串、函数(全局 before 保护模式 之后的匿名/内联中间件函数)或字符串/函数数组。更多关于命名中间件。
¥You can define middleware to apply before loading this page. It will be merged with all the other middleware used in any matching parent/child routes. It can be a string, a function (an anonymous/inlined middleware function following the global before guard pattern), or an array of strings/functions. More about named middleware.
name
你可以为此页面的路由定义一个名称。
¥You may define a name for this page's route.
path
如果你的模式比文件名所能表达的更复杂,你可以定义一个路径匹配器。有关更多信息,请参阅 vue-router
文档。
¥You may define a path matcher, if you have a more complex pattern than can be expressed with the file name. See the vue-router
docs for more information.
props
允许将路由 params
作为传递给页面组件的 props 进行访问。更多信息,请参阅 vue-router
文档。
¥Allows accessing the route params
as props passed to the page component. Seethe vue-router
docs for more information.
Typing 自定义元数据
¥Typing Custom Metadata
如果你为页面添加自定义元数据,你可能希望以类型安全的方式进行。可以扩充 definePageMeta
接受的对象类型:
¥If you add custom metadata for your pages, you may wish to do so in a type-safe way. It is possible to augment the type of the object accepted by definePageMeta
:
declare module '#app' {
interface PageMeta {
pageType?: string
}
}
// It is always important to ensure you import/export something when augmenting a type
export {}
导航
¥Navigation
要在应用的各个页面之间导航,你应该使用 <NuxtLink>
组件。
¥To navigate between pages of your app, you should use the <NuxtLink>
component.
此组件已包含在 Nuxt 中,因此你无需像导入其他组件那样导入它。
¥This component is included with Nuxt and therefore you don't have to import it as you do with other components.
指向 pages
文件夹中 index.vue
页面的简单链接:
¥A simple link to the index.vue
page in your pages
folder:
<template>
<NuxtLink to="/">Home page</NuxtLink>
</template>
:
了解更多关于 <NuxtLink>
的使用方法。
¥Learn more about <NuxtLink>
usage.
::
程序化导航
¥Programmatic Navigation
Nuxt 允许通过 navigateTo()
实用程序方法进行编程导航。使用此实用方法,你将能够以编程方式在应用中导航用户。这对于从用户那里获取输入并在整个应用中动态导航它们非常有用。在此示例中,我们有一个名为 navigate()
的简单方法,当用户提交搜索表单时会调用该方法。
¥Nuxt allows programmatic navigation through the navigateTo()
utility method. Using this utility method, you will be able to programmatically navigate the user in your app. This is great for taking input from the user and navigating them dynamically throughout your application. In this example, we have a simple method called navigate()
that gets called when the user submits a search form.
navigateTo
上使用 await
,或通过从函数返回链接其结果。<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-Only Pages
你可以通过为页面添加 .client.vue
后缀将其定义为 仅限客户端。此页面的任何内容都不会在服务器上渲染。
¥You can define a page as client only by giving it a .client.vue
suffix. None of the content of this page will be rendered on the server.
服务器专用页面
¥Server-Only Pages
你可以通过为页面添加 .server.vue
后缀将其定义为 仅限服务器。虽然你可以使用由 vue-router
控制的客户端导航导航到页面,但它将自动使用服务器组件进行渲染,这意味着渲染页面所需的代码将不会包含在你的客户端包中。
¥You can define a page as server only by giving it a .server.vue
suffix. While you will be able to navigate to the page using client-side navigation, controlled by vue-router
, it will be rendered with a server component automatically, meaning the code required to render the page will not be in your client-side bundle.
纯服务器页面必须只有一个根元素。(HTML 注释也被视为元素。)
¥Server-only pages must have a single root element. (HTML comments are considered elements as well.)
自定义路由
¥Custom Routing
随着你的应用变得越来越大、越来越复杂,你的路由可能需要更大的灵活性。在本方案中,我们将创建一个简单的 API 路由,用于基于静态数据登录用户。
¥As your app gets bigger and more complex, your routing might require more flexibility. For this reason, Nuxt directly exposes the router, routes and router options for customization in different ways.
多个页面目录
¥Multiple Pages Directories
默认情况下,所有页面都应位于项目根目录下的 pages
目录中。
¥By default, all your pages should be in one pages
directory at the root of your project.
但是,你可以使用 Nuxt 层 对应用页面进行分组:
¥However, you can use Nuxt Layers to create groupings of your app's pages:
-| 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'],
})