Динамические маршруты
У каждой статьи блога свой адрес: /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).