Маршрутизация Angular Подробное руководство
Свойства Routes
path
- путь для маршрутаcomponent
- компонент для URLpathMatch
- задает соответствие URL свойству PATH ('full
', 'prefix
'); свойство обязательно при наличииredirectTo
redirectTo
- редирект на другой URLchildren
- для задания дочерних маршрутов, которые отображают дополнительные компоненты во вложенных элементахrouter-outlet
, содержащихся в шаблоне компонента активацииoutlet
- для поддержки множественных компонентовoutlet
resolve
- определяет действия, которые должны быть совершены перед активацией маршрутаcanActive
- управляем активацией маршрутаcanActiveChild
- управляем активацией дочернего маршрутаcanDeactivate
- управляем тем, когда маршрут может деактивироваться для активации нового маршрутаloadCildren
- для настройки модуля, который загружается только в случае необходимостиcanLoad
- загрузка модулей по требованию
Порядок настройки роутинга
// app.module.ts // I import { RouterModule } from '@angular/router' @NgModule({ imports: [ // II RouterModule.forRoot([{ path: 'welcome', component: WelcomeComponent }, { path: '', redirectTo: 'welcome', pathMatch: 'full' }, { path: '**', component: PageNotFoundComponent } ]), /// III (index.html) <router-outlet></router-outlet>
Директивы RouterOutlet
Именно корневой компонент обеспечивает навигацию между разными компонентами.
RouterOutlet
- директива (<router-outlet>
) станет заполнителем, где роутер отобразит view (при этом все предыдущие компоненты будут удалены).
Именованные элементы router-outlet
router-outlet может быть несколько. Отсюда следует, что по одному маршруту можно вывести несколько компонентов, загрузив их в разные
router-outlet
.
Чтобы отличать элементы router-outlet
используется атрибут name
.
router-outlet
без атрибута name
является первичным, что равносильно outlet: "primary"
.
Использование:
<div> <router-outlet name="left"></router-outlet> </div> <div> <router-outlet name="right"></router-outlet> </div>
let routing = RouterModule.forChild([ { path: "", component: TestComponent, children: [ { path: "", children: [ // свойство outlet используется для назначения router-outlet { outlet: "primary", path: "", component: FirstComponent, }, { outlet: "left", path: "", component: SecondComponent, }, { outlet: "right", path: "", component: SecondComponent, }, ] },
Элемент base
Элемент base задает URl, с которым будут сравниваться пути маршрутизации.
<base href="/">
Директива routerLink
Директива routerLink
приказывает Angular выбрать в качестве целевого маршрута результат значения(выражения) директивы routerLink
.
<a routerLink="" routerLinkActive="active" [routerLinkActiveOptions]="{exact:true}"> Главная </a> <a routerLink="/about" routerLinkActive="active"> О сайте </a>
Выражения для routerLink
задаются в виде массива, значения которого соответствуют каждому конкретному сегменту.
<a [routerLink]="['item', 'edit', '7']">item 7</a>
Директива routerLinkActive
Для стилизации активных ссылок применяется специальная директива routerLinkActive
.
Активная ссылка с директивой [routerLink]
получает класс router-link-active
.
routerLinkActive
по умолчанию выполняет частичный поиск совпадения для активных URl. Однако это можно регулировать: если
exact
равно true
, то происходит полное сопоставление URl.
<a routerLink="/about" routerLinkActive="active" [routerLinkActiveOptions]="{exact: true}" > О сайте </a>
Служба ActivatedRoute и параметры маршрута
ActivatedRoute
- содержит информацию о маршруте связанную с компонентом, который загружен в outlet
.
Свойство ActivatedRoute
snapshot
- возвращает объект ActivatedRouteSnapshot
, который описывает текущий маршрут.
Свойства ActivatedRouteSnapshot
url
- возвращает массив объектовURLSegment
, каждый из которых описывает один сегмент URl-адреса для текущего маршрутаparams
- возвращает объектParams
с описанием параметров URlqueryParams
- возвращает объектParams
с описанием параметров запроса URlfragment
- возвращает объект string, содержащий фрагмент URl
Свойства URLSegment
Path
- строка со значением сегментаparameters
- индексированная коллекция параметров
// определение маршрутов const appRoutes: Routes =[ { path: 'item/:id', component: MyComponent}, { path: 'products/:id/edit', component: ProductEditComponent }
Маршрут вида 'item/:id
' будет соответствовать любому URl-адресу из двух сегментов, первый из которых будет содержать item
.
Второй сегмент будет содержать значение, которое присвоится параметру с именем id
.
Mы сможем обратиться к компоненту с запросом типа /item/7
, и число 7
будет представлять параметр id
.
import { Component, OnInit} from '@angular/core'; import { ActivatedRoute } from '@angular/router'; export class ProductDetailComponent implements OnInit { constructor(private productService: ProductService, private route: ActivatedRoute) { // плохая практика вызывать в конструкторе "тяжелые" операции (в том числе и связанные с route) // поэтому лучше его использовать в ngOnInit() } ngOnInit(): void { // первый вариант вытащить параметры от роутинга // snapshot - параметры route на момент инициализации let id = +this.route.snapshot.params['id']; // Анализ сегмента URl: console.log(this.route.snapshot.url[1].path); } }
Реагируем на текущие изменения навигации при помощи ActivatedRoute
Свойства класса ActivatedRoute относящиеся к Observable:
url
- возвращаетObservable<UrlSegment[]>
: набор сегментов URl при изменении маршрутаparams
- возвращаетObservable<Params>
: набор параметров при изменении маршрутаqueryParams
- возвращаетObservable<Params>
: набор параметров запроса при изменении маршрутаfragment
- возвращаетObservable<string>
: фрагмент URl при изменении маршрута
export class ProductDetailComponent implements OnInit { constructor(private route: ActivatedRoute) { // подписываемся на параметры this.route.params.subscribe( params => { let id = +params['id']; this.getProduct(id); } ); // подписываемся на GET-параметры this.route.queryParams.subscribe((params: Params) => { this.color = params['color']; this.year = params['year']; }) } }
Множественные параметры и routerLink
const routes: Routes = [ { path: "item/:mode/:id", component: ItemComponent }, { path: "item/:mode", component: ItemComponent }, { path: "", component: MainComponent } ]
Mы сможем обратиться к компоненту с запросом типа /item/edit/7
:
Выражения для routerLink задается в виде массива, значения которого соответствуют каждому конкретному сегменту.<a [routerLink]="['item', 'edit', '7']">item 7</a>
Дополнительные(необязательные) параметры маршрута
<a [routerLink] = "['/products', product.id, 'edit', { name: 'John', city: 'Moscow' }]"> Edit </a>
В браузере: http://localhost:3000/products/1/edit;name=John;city=Moscow
Получить в компоненте можно точно также как и для основных параметров (см. пример выше).
Класс Router
Класс Router
предоставляет доступ к системе навигации из компонентов.
Свойства и методы Класса Router
navigated
- возвращаетtrue
, если было хотя бы одно событие навигации, иначеfalse
.url
- возвращает активный URl-адресisActive(url, exact)
возвращаетtrue
, если заданный URl совпадает с URl, определенным активным маршрутом.events
- возвращает объект типаObservable<Event>
, который может использоваться для отслеживания навигационных изменений.navigateByUrl(url, extras)
- делаем навигацию к заданному URl-адрему.navigate(commands, extras)
- делаем навигацию по массиву сегментов.
gotoDetail(): void { this.router.navigate(['/detail', this.selectedHero.id]); // { path: 'detail/:id', component: HeroDetailComponent }, } gotoBack(): void { this.router.navigateByUrl('/'); }
Система маршрутизации уничтожает компонент после того, как он перестает отображаться.
Навигация с queryParams и хэшем
// cars?color=pink&year;=1975#pic openPage() { this.router.navigate(['./cars', 8, 'opel'], { // ?color=pink&year;=1975 queryParams: { color: 'pink', year: 1975 }, // хэш: #pic fragment: 'pic' }); }
События навигации
Некоторые компоненты должны знать о выполнении навигации, неважно задействованы они в навигации или нет.
Свойство events
объекта router
возвращает объект типа Observable<Event>
,
который может использоваться для отслеживания навигационных изменений.
Типы Event для Router.events
Event на angular.io
NavigationStart
- триггер на начало навигацииRoutesRecognized
- триггер на 'узнавание' системной марщрутаNavigationEnd
- триггер на конец навигацииNavigationCancel
- триггер на отмену навигацииNavigationError
- триггер на ошибку навигации
export class TestComponent { public testProp = 1; constructor(router: Router) { router.events .filter(e => e instanceof NavigationEnd || e instanceof NavigationCancel) .subscribe(e => { this.testProp = null; }); } }
Универсальные маршруты
**
- так обозначается путь, который может соответствовать любому URl.
@NgModule({ imports: [ //II RouterModule.forRoot([{ path: '**', component: PageNotFoundComponent } ]),
Перенаправление маршрутов
Перенаправление маршрутов определяется при помощи свойстваredirectTo
, которое задает URl на который произойдет перенаправление.
При перенаправлении должно быть задано свойства pathMatch (со значениями: full (URl полностью совпадает
со значением совйства path), prefix (URl начинается с заданного пути))
// определение маршрутов const routes: Routes = [ // pathMatch:'full' указывает, что запрошенный адрес должен полностью соответствовать маршруту { path: '', redirectTo: '/dashboard', pathMatch: 'full' }, { path: 'dashboard', component: DashboardComponent }, { path: 'detail/:id', component: HeroDetailComponent }, { path: 'heroes', component: HeroesComponent } ];
Дочерние маршруты
Дочерние маршруты позволяют компонентом реагировать на изменении URl-адреса, путем вставки в шаблон компонентов элемента
router-outlet
.
Дочерние маршруты определяются в свойстве children
.
Компоненты выбранные как дочерние маршруты отображаются в router-outlet
, который определен в родительском компоненте.
@NgModule({ imports: [ // Определение маршрутов для feature модуля RouterModule.forChild([ // "" так как подгружаем по lazy loading и в основном роутинге уже прописан путь, который зайдет сюда { path: "", component: PhraseListComponent }, { path: "phrase/:id", component: PhraseDetailsComponent }, { path: "test-animation", component: TestAnimationComponent }, { path: 'cars', component: CarsPageComponent, children: [{ path: ':id/:name', component: CarPageComponent, canActivate: [ CarsGuardTestGuard ] } ] } ]) ], exports: [ RouterModule // делаем re-export модуля для использования директив при маршрутизации, // благодаря этому данный RouterModule будет доступен в модуле, // который импортирует данный модуль ] }) export class PhrasesRoutingModule { }
Более подробно на сайте dnzl.ru: Маршрутизация Angular Подробное руководство
Комментарии к статье
Здравствуйте!
Объясните, пожалуйста, почему вы в начале статьи пишите, что не рекомендуется использовать router в конструкторе, а в конце статьи - там его и используете?
Я бы не придрался, если бы не столкнулся сейчас с тем, что не работает `this.router.events.subscribe()` в `ngOnInit()`, а вот как раз в конструкторе работает. Не пойму, почему так...