Рутинг Накста устроен так, что родительские руты имеют приоритет над дочерними: ~/pages/foo.vue > ~/pages/foo/[slug].vue
. Поскольку Накст считает [slug].vue
дочерним рутом, для его отображения необходим компонент <NuxtPage>
. Иначе [slug].vue
никогда не зарендерится.
Если вам в голову пришёл хак рендерить основную страницу, а в конце дописывать <NuxtPage v-else>
, отслеживая имя рута, — не надо. Компоненты начнут прокидываться фрагментами, возникнет ошибка parent is null
, из-за неё целиком пропадёт страница. Избавьте себя от проблем с рендерингом.
Что говорит дока
Дока рекомендует писать так: ~/pages/foo/index.vue
и ~/pages/foo/[slug].vue
. Файлы index.vue
позволяют отловить все руты уровнем ниже и перейти на них.
Но если страница описана в index.vue
, рут не считается дочерним (children). Так как useRoute().matched
полагается на дочерние руты, это ломает класс active
в ссылках <NuxtLink>
и <RouterLink>
.
Знатоки Накста предлагают ввести такую структуру папок:
/pages
/posts
[postId].vue
index.vue
posts.vue
Где posts.vue
содержит код:
<template>
<NuxtPage />
</template>
К сожалению, это приводит к дублированию рутов и всё к тому же parent is null
. Если вывести в консоль useRouter().getRoutes()
, вы увидите, что в поле matched
выводятся по два рута с одинаковым именем, но один из них содержит null
.
Знатоки предлагают обернуть каждый <NuxtPage />
дивом, чтобы заполнить null
и положить фрагменты в корневой элемент, но это полумера. К тому же, пока по всему проекту насоздаёшь этих файлов по три строчки, заработаешь геморрой.
Предлагаю написать функцию, которая определит активность ссылки по текущему URL:
// shared/lib/isLinkActiveFor.ts
export function isLinkActiveFor(pagePath: string) {
return useRoute().path.startsWith(pagePath)
}
Использование:
<NuxtLink
:to="link.href"
class="header__link p-text-lg--medium"
:class="{ 'header__link--active': isLinkActiveFor(link.href) }"
>
{{ link.title }}
</NuxtLink>
На useRoute().matched
ещё зачастую полагается компонент хлебных крошек, но его легко написать через дробление URL:
«единственный рабочий вариант для Nuxt 3»
Создавайте страницы вида static.vue
и [slug].vue
в двух случаях:
- Когда работаете с подлинными nested рутами, которые вкладываются друг в друга через
<NuxtPage>
. В этом контексте работаетmatched
. Опыт показывает, что чаще всего<NuxtPage>
нужен, чтобы прокинуть вниз лэйаут. - Когда ниже этого рута ничего нет. Для простоты, чтобы не городить папки.
В остальных случаях используйте index.vue
.
Ещё
Is index.vue always requested? Как отловить корневой рут и вложенные в одном файле.