Маршрутизация¶
В Angular маршрутизация представляет собой переход от одного представления (шаблона) к другому в зависимости от заданного URL. Причем навигация может осуществляться и внутри представления.
Навигация в Angular приложениях происходит без перезагрузки страницы.
Ключевая роль в формировании URL принадлежит тегу <base>
, указывающему путь к приложению относительно расположения файла index.html
. Если index.html
располагается в директории клиентского приложения, то тег должен быть записан следующим образом.
1 |
|
Если бы клиентское приложение находилось в директории example
, а index.html
на одном уровне иерархии с ней, то было бы так:
1 |
|
За организацию маршрутизации в Angular отвечает модуль RouterModule
библиотеки @angular/router
.
URL организуются в специальные модули и определяются для каждого отдельного модуля приложения.
Рассмотрим создание модуля AppRoutingModule
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
|
При определении маршрута можно указать ряд свойств:
path
— наименование маршрута;component
— компонент для отображения при переходе на URL, совпадающий сpath
;children
— одно из дополнительных свойств, объединяющее в себе группу маршрутов относительно текущего;data
— дополнительные данные, например, значение хлебных крошек;redirectTo
— перенаправляет на указанный URL при попадании на маршрут, указанный вpath
;pathMatch
— используется совместно сredirectTo
.
Обратите внимание, что компоненты-маршруты должны быть импортированы в модуль Angular маршрутизации.
Родительский маршрут не обязательно должен определять свойство component, он может просто объединять в себе логически связанные маршруты. Например, в примере выше contacts
— родитель для страниц с контактами.
Разберем подробно назначение свойства pathMatch
. У нас имеется маршрут contacts
, прямой переход на который вызвал бы ошибку, если бы не было определено свойство redirectTo
, поскольку для contacts
не определен компонент.
Теперь представим, что redirectTo
указан, а pathMatch
— нет. Переход по маршруту /contacts/director
отобразит компонент, указанный в redirectTo
для contacts
. Это происходит потому что при навигации на дочерний маршрут, Router
проходит по дереву иерархии все его родительские URL и при попадании на /contacts
сработает редирект.
Чтобы избежать этого в Angular routing указывается свойство pathMatch
со значением full
. И тогда перенаправление сработает только когда точно будет запрошен URL /contacts
.
Для обработки несуществующих маршрутов необходимо использовать path
со значением **
(означает любой маршрут). Таким образом, если запрошенный URL не найдет соответствий в определенной конфигурации, то маршрутизатор отобразит компонент, указанный для **
.
В Angular маршрутизации важен порядок определения URL. При запросе маршрутизатор ищет первый подходящий маршрут в порядке их определения. Поэтому обработка любого URL всегда должна определяться в самом конце.
Определение маршрутов далее передается в качестве аргумента методу forRoot()
модуля RouterModule
.
Метод forRoot() используется только при определении набора URL корневого модуля. Для остальных (дочерних) модулей используется метод forChild().
Далее AppRoutingModule
импортируется в модуль, для которого создается навигация.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
Компоненты, на которые указывает Angular routing, подгружаются в место, где указана директива <router-outlet></router-outlet>
.
Для маршрутов, находящихся на самом верхнем уровне иерархии (LoginRouteComponent
и HomeRouteComponent
), родительским служит компонент, указанный в поле bootstrap
.
1 2 3 4 5 6 7 8 9 |
|
Для перехода на дочерний маршрут (child route) необходимо указать полный путь к нему начиная с самого верхнего родителя.
То есть, чтобы увидеть ProfileRouteComponent
, нужно в адресную строку браузера ввести /home/profile
. При этом HomeRouteComponent
должен содержать директиву <router-outlet></router-outlet>
, поскольку последующая навигация происходит только внутри него самого.
home-route.component.html
1 2 3 4 |
|
Структура Angular routing определена, но как теперь перейти на описанные URL из шаблона? В AppComponent
используется компонент AppNavComponent
, в котором и определено меню приложения.
app-nav.component.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
Для перехода по заданным URL используется директива routerLink
, которая может быть указана не только у тега <a>
, но и у любого другого блочного HTML элемента.
Совместно с routerLink
используется директива routerLinkActive
. Она принимает название класса, который будет добавлен элементу (у которого указаны директивы) при активном URL, на который они ссылаются.
Как видно, все ссылки указываются от корня приложения (начинаются с /
). Но в Angular routing также возможно использование относительных ссылок.
Предположим, в HomeRouteComponent
должна содержаться ссылка на компонент ProfileComponent
. Поскольку URL для HomeComponent
(home) является родительским по отношению к URL ProfileRouteComponent
(profile). Ссылка может быть указана так:
1 2 3 4 5 |
|
Указание относительных ссылок позволяет избежать переписывания всех ссылок дочерних компонентов при изменении родительской.
Любое Angular приложение, реализующее внутри себя навигацию, имеет единственный экземпляр сервиса Router
, который хранит полную конфигурацию маршрутов и реализует API для работы с навигацией.
Наиболее часто используемым методом сервиса Router является navigate()
. В качестве первого параметра он принимает массив, где задается URL, а в качестве второго — объект с дополнительными параметрами запрашиваемого маршрута:
1 2 3 4 |
|
Маршруты с параметрами¶
Часто возникает необходимость отображения данных в зависимости от какого-то параметра, например, id
. Эти параметры обычно передаются через URL.
Модернизируем маршрут profile
, который должен отображать данные профиля по запрашиваемому id
. Также укажем хлебные крошки через свойство data
.
1 2 3 4 5 6 7 8 9 |
|
Получить значение параметра и свойства data
позволяет сервис ActivatedRoute
. В его экземпляре, определенном для компонента-маршрута, содержится полная информация.
profile.component.ts
1 2 3 4 5 6 7 8 9 10 |
|
В консоль будет выведена полная информация о текущем URL. Необходимые свойства:
url
— наименование маршрута;params
— параметры Angular маршрутизации и их значения, указываемые при определении маршрута, например,id
в/profile/:id
;queryParams
— параметры строки запроса, например,id
в/profile?id=3
;fragment
— значениеhash
, например,address
в/profile#address
;data
— объект одноименного свойства, указываемого при определении маршрута.
В шаблоне параметры маршрутизации передаются следующим образом: в качестве значения директивы указывается массив, первое значение которого URL, второе — значение параметра данного URL.
1 |
|
Параметры строки запроса и hash
имеют следующую запись:
1 2 3 |
|
1 2 3 |
|
Множественная маршрутизация (named outlets)¶
В Angular различают основные и второстепенные маршруты. В пределах одного компонента может быть только один основной маршрут и сколько угодно второстепенных.
Реализуется это с помощью директивы <router-outlet></router-outlet>
. Основной URL соответствует стандартной записи директивы, второстепенный — записи директивы с атрибутом name.
Основные и второстепенные URL полностью независимы друг от друга. Для создания второстепенного маршрута при его определении нужно указать значения атрибута name директивы <router-outlet></router-outlet>
в свойстве outlet
.
Добавим в приложение второстепенный маршрут discount-info
, который будет отображать информацию о скидках.
Обновим определение Angular routing.
1 |
|
Обновим файл app.component.html
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
Теперь в приложении в правой колонке будет отображаться информация о скидках. Чтобы отобразить/скрыть значение второстепенного маршрута, можно выполнить следующее:
1 2 3 4 5 6 7 |
|
Или из контроллера:
1 2 3 4 5 |
|
При отображении/скрытии обратите внимание на значение адресной строки браузера. В конце URL должна появляться/исчезать приписка.
1 |
|