Открыть меню    

Маршрутизация Angular Подробное руководство

Свойства Routes

  • path - путь для маршрута
  • component - компонент для URL
  • pathMatch - задает соответствие URL свойству PATH ('full', 'prefix'); свойство обязательно при наличии redirectTo
  • redirectTo - редирект на другой URL
  • children - для задания дочерних маршрутов, которые отображают дополнительные компоненты во вложенных элементах 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 с описанием параметров URl
  • queryParams - возвращает объект Params с описанием параметров запроса URl
  • fragment - возвращает объект 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:


<a [routerLink]="['item', 'edit', '7']">item 7</a>
Выражения для routerLink задается в виде массива, значения которого соответствуют каждому конкретному сегменту.

Дополнительные(необязательные) параметры маршрута


<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 Подробное руководство

Комментарии к статье

аватарка пользователя
2019-04-10
Сергей

Здравствуйте!
Объясните, пожалуйста, почему вы в начале статьи пишите, что не рекомендуется использовать router в конструкторе, а в конце статьи - там его и используете?
Я бы не придрался, если бы не столкнулся сейчас с тем, что не работает `this.router.events.subscribe()` в `ngOnInit()`, а вот как раз в конструкторе работает. Не пойму, почему так...