Nuxt/docs/content/3.docs/2.directory-structure/10.pages.md

7.1 KiB

icon title head.title
IconDirectory pages Pages directory

Pages directory

::alert{type="info"} The pages/ directory is optional, meaning that if you only use app.vue, vue-router won't be included, reducing your application's bundle size. ::

Nuxt will automatically integrate Vue Router and map pages/ directory into the routes of your application.

::alert{type=warning} Unlike components, your pages must have a single root element to allow Nuxt to apply route transitions between pages. ::

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.

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, and thus it doesn't support any non-dynamic text.

Example

-| pages/
---| index.vue
---| users-[group]/
-----| [id].vue

Given the example above, you can access group/id within your component via the $route object:

<template>
  {{ $route.params.group }}
  {{ $route.params.id }}
</template>

Navigating to /users-admins/123 would render:

admins 123

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>
const route = useRoute()

if (route.params.group === 'admins' && !route.params.id) {
  console.log('Warning! Make sure user is authenticated!')
}
</script>

Navigation

To navigate between pages of your app, you should use the  <NuxtLink> component. This component is included with Nuxt and therefore you don't have to import it as you do with other components. It is similar to the HTML <a> tag except that instead of using a href="/about" you use to="/about". If you've used vue-router before, you can think of <NuxtLink> as a replacement for <RouterLink>.

A simple link to the index.vue page in your pages folder:

<template>
  <NuxtLink to="/">Home page</NuxtLink>
</template>

The <NuxtLink> component should be used for all internal links. That means for all links to the pages within your site you should use <NuxtLink>. The <a> tag should be used for all external links. That means if you have links to other websites you should use the <a> tag for those.

<template>
  <div>
    <h1>Home page</h1>
    <NuxtLink to="/about">
      About (internal link that belongs to the Nuxt App)
    </NuxtLink>
    <a href="https://nuxtjs.org">External Link to another page</a>
  </div>
</template>

::alert{type="info"} If you want to know more about <RouterLink>, read the Vue Router documentation for more information. ::

Nested Routes

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'
      }
    ]
  }
]

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>

Child route keys

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="someKey" />
  </div>
</template>

Or alternatively:

<script setup>
definePageMeta({
  key: route => route.fullPath
})
</script>

Page Metadata

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>
definePageMeta({
  title: 'My home page'
})
</script>

This data can then be accessed throughout the rest of your app from the route.meta object.

<script setup>
const route = useRoute()
console.log(route.meta.title) // My home page
</script>

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.

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 (or values defined on the component). However, it can reference imported bindings.

<script setup>
import { someData } from '~/utils/example'

const title = ref('')

definePageMeta({
  title,
  someData
})
</script>

Special Metadata

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:

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 which has dynamic child routes, if you want to preserve page state across route changes. You can also set props to be passed to <KeepAlive>.

key

See above.

layout

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.

middleware

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.

layoutTransition and pageTransition

You can define transition properties for the <transition> components that wraps your pages and layouts, or pass false to disable the <transition> wrapper for that route. More about transitions.