3. Файловая маршрутизация
🗂️ Файловая маршрутизация в Nuxt 3
Заголовок раздела «🗂️ Файловая маршрутизация в Nuxt 3»Одна из самых мощных фич Nuxt — файловая маршрутизация. Создал файл в pages/ — получил маршрут. Никаких настроек, никаких createRouter. Структура папок = структура URL.
Как это работает 🔮
Заголовок раздела «Как это работает 🔮»Nuxt сканирует директорию pages/ и автоматически создаёт конфигурацию Vue Router:
pages/├── index.vue → /├── about.vue → /about├── contact.vue → /contact└── blog/ ├── index.vue → /blog └── first-post.vue → /blog/first-postНи строки настройки роутера не нужно. Всё работает автоматически.
app.vue с NuxtPage 📌
Заголовок раздела «app.vue с NuxtPage 📌»<template> <div> <!-- NuxtPage — это <RouterView> от Nuxt --> <NuxtPage /> </div></template>Типы маршрутов 📂
Заголовок раздела «Типы маршрутов 📂»Статические маршруты
Заголовок раздела «Статические маршруты»pages/index.vue → /pages/about.vue → /aboutpages/blog/index.vue → /blogpages/users/profile.vue → /users/profileДинамические маршруты — [param]
Заголовок раздела «Динамические маршруты — [param]»pages/blog/[slug].vue → /blog/:slugpages/users/[id].vue → /users/:idpages/[category]/[id].vue → /:category/:id<script setup lang="ts">const route = useRoute()// route.params.slug — текущий slugconst slug = route.params.slug as string
// Загружаем пост по slugconst { data: post } = await useFetch(\`/api/posts/\${slug}\`)</script>
<template> <article> <h1>{{ post?.title }}</h1> <p>slug: {{ $route.params.slug }}</p> </article></template>Catch-all маршруты — [...slug]
Заголовок раздела «Catch-all маршруты — [...slug]»pages/[...slug].vue → /anything/deep/pathpages/docs/[...path].vue → /docs/guide/intro/setup<script setup>const route = useRoute()// route.params.slug — массив сегментов// URL: /a/b/c → ['a', 'b', 'c']const breadcrumbs = computed(() => (route.params.slug as string[]).map((s, i, arr) => ({ name: s, path: '/' + arr.slice(0, i + 1).join('/') })))</script>Опциональный catch-all — [[...slug]]
Заголовок раздела «Опциональный catch-all — [[...slug]]»pages/[[...slug]].vue → / и /anything/deep/pathВложенные маршруты 🪆
Заголовок раздела «Вложенные маршруты 🪆»Для вложенных роутов нужна директория с файлом .vue того же имени:
pages/└── users/ ├── index.vue → /users (список) └── [id]/ ├── index.vue → /users/:id (профиль) ├── edit.vue → /users/:id/edit └── settings.vue → /users/:id/settingsИли с вложенным NuxtPage (настоящие nested routes):
pages/├── parent.vue → /parent (с <NuxtPage> внутри)└── parent/ ├── child-a.vue → /parent/child-a └── child-b.vue → /parent/child-b<template> <div> <h1>Родительская страница</h1> <nav> <NuxtLink to="/parent/child-a">Child A</NuxtLink> <NuxtLink to="/parent/child-b">Child B</NuxtLink> </nav> <!-- Дочерний роут рендерится здесь --> <NuxtPage /> </div></template>NuxtLink — навигация между страницами 🔗
Заголовок раздела «NuxtLink — навигация между страницами 🔗»<template> <!-- Базовый NuxtLink --> <NuxtLink to="/">Главная</NuxtLink> <NuxtLink to="/about">О нас</NuxtLink>
<!-- Динамический маршрут --> <NuxtLink :to="\`/blog/\${post.slug}\`">{{ post.title }}</NuxtLink>
<!-- Именованный маршрут --> <NuxtLink :to="{ name: 'blog-slug', params: { slug: 'hello' } }"> Статья </NuxtLink>
<!-- С query параметрами --> <NuxtLink :to="{ path: '/search', query: { q: 'nuxt' } }"> Поиск </NuxtLink>
<!-- Внешняя ссылка --> <NuxtLink to="https://nuxt.com" external>Сайт Nuxt</NuxtLink>
<!-- Активный класс --> <NuxtLink to="/about" active-class="text-green-500" exact-active-class="font-bold" > О нас </NuxtLink>
<!-- Prefetch (предзагрузка по умолчанию) --> <NuxtLink to="/heavy-page" :prefetch="false"> Тяжёлая страница </NuxtLink></template>definePageMeta — мета-данные страницы 📋
Заголовок раздела «definePageMeta — мета-данные страницы 📋»<script setup lang="ts">definePageMeta({ // Название маршрута name: 'admin-dashboard',
// Layout для этой страницы layout: 'admin',
// Middleware для этой страницы middleware: ['auth', 'admin-only'],
// Мета-данные (для кастомного использования) requiresAuth: true, roles: ['admin', 'superadmin'],
// Алиас alias: ['/dashboard', '/admin'],
// Переходы pageTransition: { name: 'slide', mode: 'out-in' },
// Keepalive keepalive: true,})</script><script setup>definePageMeta({ // Отключить layout layout: false,})</script>Программная навигация 🧭
Заголовок раздела «Программная навигация 🧭»<script setup>const router = useRouter()const route = useRoute()
// Переход на страницуawait router.push('/about')await router.push({ name: 'users-id', params: { id: 1 } })
// Замена текущей записи в историиawait router.replace('/login')
// Назад/Вперёдrouter.back()router.forward()router.go(-2)
// Текущий маршрутconsole.log(route.path) // '/blog/hello-world'console.log(route.params) // { slug: 'hello-world' }console.log(route.query) // { page: '2' }console.log(route.hash) // '#section'console.log(route.name) // 'blog-slug'console.log(route.fullPath) // '/blog/hello-world?page=2#section'</script>Специальные имена файлов 📌
Заголовок раздела «Специальные имена файлов 📌»pages/├── index.vue → / (главная)├── [...slug].vue → catch-all├── [[slug]].vue → опциональный параметр└── (group)/ ← группа (без влияния на URL) ├── page-a.vue → /page-a └── page-b.vue → /page-bИгнорирование файлов:
pages/└── -drafts/ ← файлы с - в начале игнорируются └── new-post.vue ← не создаёт роутuseRouter и useRoute — типизация 🔷
Заголовок раздела «useRouter и useRoute — типизация 🔷»С typedPages: true в nuxt.config.ts:
export default defineNuxtConfig({ experimental: { typedPages: true }})<script setup lang="ts">// Автоматически типизированные параметры!const route = useRoute('blog-slug')// route.params.slug — TypeScript знает, что это string
const router = useRouter()// TypeScript подскажет доступные роутыawait router.push({ name: 'users-id', params: { id: '123' } })</script>Переходы между страницами 🎨
Заголовок раздела «Переходы между страницами 🎨»<template> <NuxtPage :page-key="route => route.fullPath" /></template>
<style>.page-enter-active,.page-leave-active { transition: all 0.3s ease;}.page-enter-from,.page-leave-to { opacity: 0; transform: translateY(20px);}</style>Или через конфиг:
export default defineNuxtConfig({ app: { pageTransition: { name: 'page', mode: 'out-in' }, }})Полезные паттерны 🎯
Заголовок раздела «Полезные паттерны 🎯»Получение данных в зависимости от роута
Заголовок раздела «Получение данных в зависимости от роута»<script setup lang="ts">const route = useRoute()
// Реактивно обновляется при смене :idconst { data: user, refresh } = await useFetch( () => \`/api/users/\${route.params.id}\`)
// Следим за сменой параметровwatch(() => route.params.id, () => refresh())</script>Breadcrumbs из маршрута
Заголовок раздела «Breadcrumbs из маршрута»<script setup>const route = useRoute()
const breadcrumbs = computed(() => { const paths = route.path.split('/').filter(Boolean) return paths.map((segment, index) => ({ label: segment, to: '/' + paths.slice(0, index + 1).join('/') }))})</script>