Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

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

У каждой статьи блога свой адрес: /posts/1, /posts/2 и так далее. Создавать файл на каждую статью нельзя, поэтому часть адреса делают параметром — переменной, значение которой берётся из адреса. В имени файла параметр записывают в квадратных скобках.

Страница статьи

Создайте страницу командой:

npx nuxi add page "posts/[id]"

Появится файл app/pages/posts/[id].vue. Он обслуживает все адреса вида /posts/что-угодно. Замените содержимое:

<!-- app/pages/posts/[id].vue -->
<script setup lang="ts">
const route = useRoute()
</script>
 
<template>
  <section>
    <h2>Статья номер {{ route.params.id }}</h2>
  </section>
</template>

useRoute() возвращает текущий маршрут, а route.params.id — значение параметра id. Откройте /posts/7 — на странице будет «Статья номер 7».

Поиск статьи по номеру

Пока статьи хранятся в массиве, найдём нужную:

<!-- app/pages/posts/[id].vue -->
<script setup lang="ts">
const posts = [
  { id: 1, title: 'Первый пост', text: 'Привет, мир!' },
  { id: 2, title: 'Изучаем Nuxt', text: 'Страницы из файлов.' }
]
 
const route = useRoute()
const post = computed(() => posts.find((p) => p.id === Number(route.params.id)))
</script>
 
<template>
  <article>
    <template v-if="post">
      <h2>{{ post.title }}</h2>
      <p>{{ post.text }}</p>
    </template>
    <p v-else>Статья не найдена.</p>
  </article>
</template>

По адресу /posts/2 появится статья «Изучаем Nuxt», а по /posts/99 — «Статья не найдена».

Ссылка на статью

В списке app/pages/posts/index.vue сделайте заголовки ссылками:

<!-- app/pages/posts/index.vue -->
<h3>
  <NuxtLink :to="`/posts/${post.id}`">{{ post.title }}</NuxtLink>
</h3>

Адрес собирается из номера статьи. Щелчок по заголовку открывает её страницу.

Другие виды параметров

ФайлПодходит для адресовЗначение параметра
posts/[id].vue/posts/5'5'
[category]/[slug].vue/vue/propsдва параметра
archive/[[year]].vue/archive и /archive/2024параметр необязателен
docs/[...slug].vue/docs/a/b/cмассив ['a', 'b', 'c']

Двойные скобки делают параметр необязательным, многоточие собирает все оставшиеся части адреса.

Проверка параметра

Чтобы страница открывалась только для чисел, добавьте проверку в definePageMeta:

<!-- app/pages/posts/[id].vue -->
<script setup lang="ts">
definePageMeta({
  validate: (route) => /^\d+$/.test(String(route.params.id))
})
</script>

Если функция вернёт false, Nuxt покажет ошибку 404: адрес /posts/abc больше не откроет страницу статьи.

Частая ошибка

Параметры из адреса всегда строки. Сравнение p.id === route.params.id никогда не сработает, ведь 1 и '1' для оператора === разные значения. Перед сравнением превращайте параметр в число: Number(route.params.id).

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.