pages

Nuxt предоставляет маршрутизацию на основе файлов в приложении.
Чтобы уменьшить размер бандла, каталог pages/необязателен: vue-router не подключается, если используется только app.vue. Чтобы явно включить файловый роутинг, задайте pages: true в nuxt.config или добавьте router.options.ts.

Использование

Страницы — это Vue-компоненты с любым поддерживаемым расширением (по умолчанию .vue, .js, .jsx, .mjs, .ts или .tsx).

Nuxt автоматически создает маршрут для каждой страницы в вашей директории ~/pages/.

<template>
  <h1>Index page</h1>
</template>

Файл pages/index.vue будет иметь маршрут / в вашем приложении.

Если используется app.vue, для вывода текущей страницы нужен <NuxtPage/>:

app.vue
<template>
  <div>
    <!-- Разметка, общая для всех страниц, например, NavBar -->
    <NuxtPage />
  </div>
</template>

Страницы должны иметь один корневой элемент, чтобы между ними работали анимационные переходы. HTML-комментарии тоже считаются элементами.

Это означает, что когда маршрут рендерится на сервере или генерируется статически, вы сможете увидеть его содержимое правильно, но когда вы перейдете к этому маршруту во время навигации на клиенте, переход между маршрутами будет неудачным, и вы увидите, что маршрут не рендерится.

Вот несколько примеров, которые иллюстрируют, как выглядит страница с одним корневым элементом:

<template>
  <div>
    <!-- Эта страница правильно содержит один корневой элемент -->
    Контент страницы
  </div>
</template>

Динамические маршруты

Содержимое в квадратных скобках в имени файла или папки становится параметром динамического маршрута. Можно комбинировать несколько параметров и обычный текст в пути.

Чтобы параметр был необязательным, заключите его в двойные скобки: ~/pages/[[slug]]/index.vue или ~/pages/[[slug]].vue — тогда подойдут и /, и /test.

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

Данный пример показывает, что вы можете получить доступ к group/id внутри вашего компонента через объект $route:

pages/users-[group]/[id].vue
<template>
  <p>{{ $route.params.group }} - {{ $route.params.id }}</p>
</template>

При переходе по маршруту /users-admins/123 отрендерит:

<p>admins - 123</p>

Если вы используете Composition API, то доступ к объекту маршрута можно получить, вызвав глобальную функцию useRoute, которая позволит вам получить доступ к маршруту так же, как this.$route в Options API.

<script setup lang="ts">
const route = useRoute()

if (route.params.group === 'admins' && !route.params.id) {
  console.log('Внимание! Убедитесь, что пользователь прошел аутентификацию!')
}
</script>
Именованные родительские маршруты имеют приоритет над вложенными динамическими маршрутами. Для маршрута /foo/hello, ~/pages/foo.vue будет иметь приоритет над ~/pages/foo/[slug].vue.
Используйте ~/pages/foo/index.vue и ~/pages/foo/[slug].vue для сопоставления /foo и /foo/hello между разными страницами.

Catch-all маршрут

Если нужен catch-all-маршрут, добавьте файл [...slug].vue. Он будет соответствовать всем маршрутам по этому пути.

pages/[...slug].vue
<template>
  <p>{{ $route.params.slug }}</p>
</template>

При переходе по маршруту /hello/world отрендерит:

<p>["hello", "world"]</p>

Вложенные маршруты

Вложенные маршруты задаются через <NuxtPage>.

Пример:

Directory Structure
-| 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:

pages/parent.vue
<template>
  <div>
    <h1>Я родительский элемент</h1>
    <NuxtPage :foobar="123" />
  </div>
</template>
pages/parent/child.vue
<script setup lang="ts">
const props = defineProps({
  foobar: String,
})

console.log(props.foobar)
</script>

Ключи дочерних маршрутов

Если вы хотите больше контролировать повторный рендер <NuxtPage> компонента (например, для переходов), то вы можете передавать строку или функцию во входной параметр pageKey или определить значение key через definePageMeta:

pages/parent.vue
<template>
  <div>
    <h1>Я родительский элемент</h1>
    <NuxtPage :page-key="route => route.fullPath" />
  </div>
</template>

Или:

pages/parent/child.vue
<script setup lang="ts">
definePageMeta({
  key: route => route.fullPath,
})
</script>
Прочитайте и отредактируйте живой пример в Docs > 3 X > Examples > Routing > Pages.

Группы маршрутов

В некоторых случаях вам может понадобиться сгруппировать набор маршрутов таким образом, чтобы это не повлияло на маршрутизацию на основе файлов. Для этой цели вы можете поместить файлы в директорию, заключенную в скобки - ( и ).

Например:

Directory structure
-| pages/
---| index.vue
---| (marketing)/
-----| about.vue
-----| contact.vue

Это создаст в приложении страницы /, /about и /contact. Группа marketing игнорируется в структуре URL-адреса.

Доступ к группам маршрутов

Группы маршрутов автоматически попадают в метаданные маршрута как route.meta.groups. Так можно использовать информацию о группе в компонентах для условной логики, стилей и других задач.

pages/(marketing)/about.vue
<script setup lang="ts">
const route = useRoute()

console.log(route.meta.groups) // Output: ['marketing']
</script>

<template>
  <div>
    <p v-if="route.meta.groups?.includes('marketing')">
      Это маркетинговая страница
    </p>
  </div>
</template>

Метаданные страницы

Метаданные маршрута задаются макросом definePageMeta — и в <script>, и в <script setup>:

<script setup lang="ts">
definePageMeta({
  title: 'Моя основная страница',
})
</script>

Они доступны в приложении через route.meta.

<script setup lang="ts">
const route = useRoute()

console.log(route.meta.title) // Моя основная страница
</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, // так делать нельзя: ref будет вынесен из компонента
})
</script>

Особые поля метаданных

Свои ключи в definePageMeta можно задавать свободно. Ниже — поля со специальным смыслом в Nuxt:

alias

Псевдонимы маршрута: та же страница открывается по разным путям. Значение — строка или массив строк, см. документацию vue-router.

keepalive

При keepalive: true в definePageMeta Nuxt оборачивает страницу в <KeepAlive> — удобно для сохранения состояния, например у родителя с динамическими дочерними маршрутами.

Для родительских маршрутов можно использовать <NuxtPage keepalive /> и передать пропсы в <KeepAlive> (список).

Вы также можете установить значения по умолчанию для этого свойства в вашем nuxt.config.

key

См. выше.

layout

Можно задать лейаут для маршрута: false (без лейаута), строка с именем или ref/computed для реактивного выбора. Подробнее о лейаутах.

layoutTransition и pageTransition

Можно задать опции для <transition> вокруг страниц и лейаутов или передать false, чтобы отключить обёртку. Список опций — в API Vue, поведение — в руководстве.

Вы также можете установить значения по умолчанию для этого свойства в вашем nuxt.config.

middleware

Middleware до загрузки страницы сливается с цепочками родительских и дочерних маршрутов. Допустимы строка, функция в духе global before guards vue-router или массив. Подробнее — middleware маршрута.

name

Вы можете задать имя для маршрута страницы.

path

Поле path задаёт собственный шаблон маршрута, если имени файла недостаточно. См. vue-router.

props

Пробрасывает params маршрута в страницу как пропсы. См. vue-router.

Типизация пользовательских мета-данных

Если вы хотите добавить типизацию мета-данных на ваши страницы, вы можете сделать это безопасным способом. Можно дополнить тип объекта, принимаемого definePageMeta:

index.d.ts
declare module '#app' {
  interface PageMeta {
    pageType?: string
  }
}

// При расширении типов важно импортировать или экспортировать хотя бы один символ
export {}

Навигация

Для навигации между страницами в вашем приложении вы можете использовать компонент <NuxtLink>.

Этот компонент входит в состав Nuxt, его не нужно импортировать вручную, в отличие от обычных компонентов.

Например, ссылка на страницу index.vue в папке pages:

<template>
  <NuxtLink to="/">Домашняя страница</NuxtLink>
</template>
Подробнее об использовании <NuxtLink>.

Программная навигация

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, она будет автоматически рендериться серверным компонентом, что означает, что код, необходимый для рендеринга страницы, не будет включен в ваш клиентский бандл.

Страницы, предназначенные только для сервера, должны иметь один корневой элемент. (HTML-комментарии также считаются элементами).

Пользовательский роутинг

По мере роста и усложнения вашего приложения маршрутизация может потребовать большей гибкости. По этой причине Nuxt напрямую предоставляет маршрутизатор, маршруты и опции маршрутизатора для настройки различными способами.

Узнать больше Docs > 3 X > Guide > Recipes > Custom Routing.

Многостраничная директория

По умолчанию все ваши страницы находятся в корне вашего проекта в директории pages.

Однако вы можете использовать слои Nuxt для создания групп страниц вашего приложения:

Directory Structure
-| some-app/
---| nuxt.config.ts
---| pages/
-----| app-page.vue
-| nuxt.config.ts
some-app/nuxt.config.ts
// some-app/nuxt.config.ts
export default defineNuxtConfig({
})
nuxt.config.ts
export default defineNuxtConfig({
  extends: ['./some-app'],
})
Узнать больше Docs > 3 X > Guide > Going Further > Layers.