Вложенные маршруты
Некоторые пользовательские интерфейсы приложений состоят из вложенных на нескольких уровнях компонентов. В этом случае часто бывает так, что сегменты URL соответствуют определенной структуре вложенных компонентов, например:
/user/johnny/profile /user/johnny/posts
┌──────────────────┐ ┌──────────────────┐
│ User │ │ User │
│ ┌──────────────┐ │ │ ┌──────────────┐ │
│ │ Profile │ │ ●────────────▶ │ │ Posts │ │
│ │ │ │ │ │ │ │
│ └──────────────┘ │ │ └──────────────┘ │
└──────────────────┘ └──────────────────┘
Во Vue Router эти отношения можно выразить с помощью настройки вложенных маршрутов.
В качестве примера можно привести приложение, созданное нами в предыдущей главе:
<!-- App.vue -->
<template>
<router-view />
</template>
<!-- User.vue -->
<template>
<div>
User {{ $route.params.id }}
</div>
</template>
import User from './User.vue'
// маршруты передаются в `createRouter`
const routes = [{ path: '/user/:id', component: User }]
Здесь <router-view>
- это router-view
верхнего уровня. Он отображает компонент, соответствующий маршруту верхнего уровня. Аналогично, рендеримый компонент может содержать собственные вложенные <router-view>
. Например, если мы добавим его внутрь шаблона компонента User
:
<!-- User.vue -->
<template>
<div class="user">
<h2>User {{ $route.params.id }}</h2>
<router-view />
</div>
</template>
Чтобы рендерить компоненты в этот вложенный router-view
, необходимо использовать опцию children
в любом из маршрутов:
const routes = [
{
path: '/user/:id',
component: User,
children: [
{
// UserProfile будет отрендерен внутри <router-view> компонента User
// при соответствии /user/:id/profile
path: 'profile',
component: UserProfile,
},
{
// UserPosts будет отрендерен внутри <router-view> компонента User
// при соответствии /user/:id/posts
path: 'posts',
component: UserPosts,
},
],
},
]
Обратите внимание, что вложенные пути, начинающиеся с /
, будут рассматриваться как корневые. Это позволяет вам использовать вложенность компонентов без необходимости использовать вложенного URL.
Как видите, опция children
представляет собой еще один массив маршрутов, подобно самим routes
. Следовательно, вы можете вкладывать представления насколько вам нужно.
На этом этапе, при посещении /user/eduardo
, внутри router-view
компонента User
рендерится ничего не будет, потому что не будет совпадать ни один вложенный маршрут. Возможно, вы хотите что-то отображать там. В таком случае вы можете предоставить пустой вложенный путь:
const routes = [
{
path: '/user/:id',
component: User,
children: [
// UserHome будет отрендерен внутри <router-view> компонента User
// при соответствии /user/:id
{ path: '', component: UserHome },
// ...другие вложенные маршруты
],
},
]
Рабочее демо этого примера можно найти здесь.
Вложенные именованные маршруты
При работе с Именованными маршрутами обычно именуют дочерние маршруты:
const routes = [
{
path: '/user/:id',
component: User,
// обратите внимание, что только дочерний маршрут имеет имя
children: [{ path: '', name: 'user', component: UserHome }],
},
]
Таким образом, при переходе к /user/:id
всегда будет отображаться вложенный маршрут.
В некоторых сценариях вы можете захотеть перейти на именованный маршрут, не переходя на вложенный. Например, если вы хотите перейти на /user/:id
без отображения вложенного маршрута. В этом случае вы также можете дать имя родительскому маршруту, но имейте в виду, что перезагрузка страницы всегда отобразит вложенного потомка, так как она рассматривается как переход на /users/:id
, а не к именованному маршруту:
const routes = [
{
path: '/user/:id',
name: 'user-parent',
component: User,
children: [{ path: '', name: 'user', component: UserHome }],
},
]
Исключение родительских компонентов 4.1+
Мы также можем воспользоваться отношением родитель-потомок между маршрутами, не обязательно вкладывая компоненты маршрутов друг в друга. Это может быть полезно для группировки маршрутов с общим префиксом пути или при работе с более продвинутыми функциями, такими как навигационные хуки на уровне маршрута или метаданные маршрута.
Для этого мы опускаем опции component
и components
из родительского маршрута:
const routes = [
{
path: '/admin',
children: [
{ path: '', component: AdminOverview },
{ path: 'users', component: AdminUserList },
{ path: 'users/:id', component: AdminUserDetails },
],
},
]
Поскольку родительский маршрут не указывает компонент маршрута, <router-view>
верхнего уровня пропустит компонент родителя и просто использует компонент из соответствующего дочернего маршрута.