Общие задачи маршрутизации¶
28.02.2022
В этой теме описывается, как реализовать многие из общих задач, связанных с добавлением маршрутизатора Angular в ваше приложение.
Генерация приложения с включенной маршрутизацией¶
Следующая команда использует Angular CLI для генерации базового приложения Angular с модулем маршрутизации приложения, называемым AppRoutingModule
, который представляет собой NgModule, где вы можете настроить маршруты. Имя приложения в следующем примере — routing-app
.
1 |
|
Добавление компонентов для маршрутизации¶
Чтобы использовать маршрутизатор Angular, приложение должно иметь как минимум два компонента, чтобы можно было переходить от одного к другому. Чтобы создать компонент с помощью CLI, введите в командной строке следующее, где first
— имя вашего компонента:
1 |
|
Повторите этот шаг для второго компонента, но дайте ему другое имя. Здесь новое имя будет second
.
1 |
|
CLI автоматически добавляет Component
, поэтому если бы вы написали first-component
, ваш компонент был бы FirstComponentComponent
.
<base href>
Это руководство работает с приложением Angular, созданным с помощью CLI. Если вы работаете вручную, убедитесь, что у вас есть <base href="/">
в <head>
вашего файла index.html.
Это предполагает, что папка app
является корнем приложения, и использует "/"
.
Импортирование новых компонентов¶
Чтобы использовать ваши новые компоненты, импортируйте их в AppRoutingModule
в верхней части файла, как показано ниже:
1 2 |
|
Определение базового маршрута¶
Создание маршрута состоит из трех основных компонентов.
Импортируйте AppRoutingModule
в AppModule
и добавьте его в массив imports
.
Angular CLI выполнит этот шаг за вас. Однако если вы создаете приложение вручную или работаете с существующим приложением без CLI, проверьте правильность импорта и конфигурации.
Ниже приведен стандартный AppModule
, использующий CLI с флагом --routing
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
-
Импортируйте
RouterModule
иRoutes
в ваш модуль маршрутизации.Angular CLI выполняет этот шаг автоматически.
CLI также устанавливает массив
Routes
для ваших маршрутов и настраивает массивыimports
иexports
для@NgModule()
.1 2 3 4 5 6 7 8 9 10 11
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; // CLI imports router const routes: Routes = []; // sets up routes constant where you define your routes // configures NgModule imports and exports @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule], }) export class AppRoutingModule {}
-
Определите маршруты в массиве
Routes
.Каждый маршрут в этом массиве представляет собой объект JavaScript, который содержит два свойства.
Первое свойство,
path
, определяет путь URL для маршрута.Второе свойство,
component
, определяет компонент, который Angular должен использовать для соответствующего пути.1 2 3 4 5 6 7 8 9 10
const routes: Routes = [ { path: 'first-component', component: FirstComponent, }, { path: 'second-component', component: SecondComponent, }, ];
-
Добавьте маршруты в приложение.
Теперь, когда вы определили маршруты, добавьте их в приложение.
Сначала добавьте ссылки на два компонента.
Присвойте тегу якоря, в который вы хотите добавить маршрут, атрибут
routerLink
.Установите значение атрибута для компонента, который будет отображаться, когда пользователь нажмет на каждую ссылку.
Далее обновите шаблон компонента, включив в него
<router-outlet>
.Этот элемент сообщает Angular обновить представление приложения компонентом для выбранного маршрута.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
<h1>Angular Router App</h1> <!-- This nav gives you links to click, which tells the router which route to use (defined in the routes constant in AppRoutingModule) --> <nav> <ul> <li> <a routerLink="/first-component" routerLinkActive="active" ariaCurrentWhenActive="page" >First Component</a > </li> <li> <a routerLink="/second-component" routerLinkActive="active" ariaCurrentWhenActive="page" >Second Component</a > </li> </ul> </nav> <!-- The routed views render in the <router-outlet>--> <router-outlet></router-outlet>
Порядок маршрутов¶
Порядок маршрутов важен, поскольку Router
использует стратегию выигрыша по первому совпадению при подборе маршрутов, поэтому более конкретные маршруты должны располагаться выше менее конкретных. Сначала перечисляются маршруты со статическим путем, затем пустой маршрут, который соответствует маршруту по умолчанию.
Маршрут wildcard route идет последним, потому что он соответствует каждому URL, и Router
выбирает его только в том случае, если ни один другой маршрут не подходит первым.
Получение информации о маршруте¶
Часто, когда пользователь перемещается по вашему приложению, вы хотите передавать информацию от одного компонента к другому. Например, рассмотрим приложение, которое отображает список покупок продуктов.
Каждый элемент в списке имеет уникальный id
.
Чтобы отредактировать элемент, пользователи нажимают кнопку Edit, которая открывает компонент EditGroceryItem
.
Вы хотите, чтобы этот компонент получал id
для бакалейного товара, чтобы он мог отображать правильную информацию пользователю.
Используйте маршрут для передачи такого типа информации компонентам приложения. Для этого вы используете функцию withComponentInputBinding с provideRouter
или опцию bindToComponentInputs
в RouterModule.forRoot
.
Чтобы получить информацию из маршрута:
-
Добавьте функцию
withComponentInputBinding
к методуprovideRouter
.1 2 3 4 5 6
providers: [ provideRouter( appRoutes, withComponentInputBinding() ), ];
-
Обновите компонент, чтобы у него был
Input
, соответствующий имени параметра.1 2 3 4
@Input() set id(heroId: string) { this.hero$ = this.service.getHero(heroId); }
Вы можете привязать все данные маршрута с парами ключ-значение к входам компонента: статические или разрешенные данные маршрута, параметры пути, параметры матрицы и параметры запроса.
Настройка маршрутов wildcard¶
Хорошо функционирующее приложение должно изящно обрабатывать попытки пользователей перейти к несуществующей части вашего приложения. Чтобы добавить эту функциональность в ваше приложение, вы устанавливаете маршрут wildcard
.
Маршрутизатор Angular выбирает этот маршрут каждый раз, когда запрашиваемый URL не соответствует ни одному пути маршрутизатора.
Чтобы настроить маршрут с подстановочным знаком, добавьте следующий код в определение routes
.
1 |
|
Две звездочки, **
, указывают Angular, что это определение routes
является маршрутом с подстановочным знаком. Для свойства component вы можете определить любой компонент в вашем приложении.
Обычно это PageNotFoundComponent
, который можно определить как отображение страницы 404 для ваших пользователей; или перенаправление на основной компонент вашего приложения.
Маршрут с подстановочным знаком — это последний маршрут, поскольку он соответствует любому URL.
Подробнее о том, почему порядок имеет значение для маршрутов, смотрите в разделе Порядок маршрутов.
Отображение страницы 404¶
Чтобы отобразить страницу 404, настройте wildcard route со свойством component
, установленным на компонент, который вы хотите использовать для страницы 404, следующим образом:
1 2 3 4 5 6 7 8 9 |
|
Последний маршрут с path
в **
является маршрутом с подстановочным знаком. Маршрутизатор выбирает этот маршрут, если запрашиваемый URL не соответствует ни одному из предыдущих в списке путей, и отправляет пользователя на PageNotFoundComponent
.
Настройка перенаправлений¶
Чтобы настроить перенаправление, настройте маршрут с путем
, с которого вы хотите перенаправить, компонентом
, на который вы хотите перенаправить, и значением pathMatch
, которое указывает маршрутизатору, как сопоставить URL.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
В этом примере третий маршрут является перенаправлением, так что маршрутизатор по умолчанию переходит к маршруту first-component
. Обратите внимание, что этот перенаправление предшествует маршруту с подстановочным знаком.
Здесь path: ''
означает использование начального относительного URL (''
).
Более подробно о pathMatch
смотрите Spotlight on pathMatch
.
Вложенные маршруты¶
По мере роста сложности вашего приложения вы можете захотеть создать маршруты, которые будут относиться к компоненту, отличному от корневого компонента. Такие типы вложенных маршрутов называются дочерними маршрутами.
Это означает, что вы добавляете второй <router-outlet>
в ваше приложение, поскольку он является дополнением к <router-outlet>
в AppComponent
.
В этом примере есть два дополнительных дочерних компонента, child-a
и child-b
. Здесь FirstComponent
имеет свою собственную <nav>
и второй <router-outlet>
в дополнение к тому, который находится в AppComponent
.
1 2 3 4 5 6 7 8 9 10 |
|
Дочерний маршрут подобен любому другому маршруту, так как ему нужны путь
и компонент
. Единственное отличие заключается в том, что дочерние маршруты размещаются в массиве children
внутри родительского маршрута.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
Установка заголовка страницы¶
Каждая страница в вашем приложении должна иметь уникальный заголовок, чтобы ее можно было идентифицировать в истории браузера. Маршрутизатор Router
устанавливает заголовок документа, используя свойство title
из конфигурации Route
.
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 |
|
Свойство title
подчиняется тем же правилам, что и статические маршрутные data
и динамические значения, реализующие ResolveFn
.
Вы также можете создать собственную стратегию заголовка, расширив TitleStrategy
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
Использование относительных путей¶
Относительные пути позволяют определять пути, которые являются относительными по отношению к текущему сегменту URL. Следующий пример показывает относительный путь к другому компоненту, second-component
.
FirstComponent
и SecondComponent
находятся на одном уровне в дереве, однако ссылка на SecondComponent
расположена внутри FirstComponent
, что означает, что маршрутизатор должен подняться на один уровень вверх, а затем во второй каталог, чтобы найти SecondComponent
.
Вместо того чтобы писать весь путь к SecondComponent
, используйте обозначение ../
для перехода на уровень выше.
1 2 3 4 5 6 7 8 9 10 11 12 |
|
В дополнение к ../
, используйте ./
или без ведущей косой черты для указания текущего уровня.
Указание относительного маршрута¶
Чтобы указать относительный маршрут, используйте свойство NavigationExtras
relativeTo
. В классе компонента импортируйте NavigationExtras
из @angular/router
.
Затем используйте relativeTo
в своем методе навигации. После массива параметров ссылки, который здесь содержит items
, добавьте объект со свойством relativeTo
, установленным на ActivatedRoute
, которым является this.route
.
1 2 3 |
|
Аргументы navigate()
настраивают маршрутизатор на использование текущего маршрута в качестве основы для добавления items
.
Метод goToItems()
интерпретирует URI назначения как относительный к активированному маршруту и переходит к маршруту items
.
Доступ к параметрам запроса и фрагментам¶
Иногда функции вашего приложения требуют доступа к части маршрута, например, к параметру запроса или фрагменту. Приложение Tour of Heroes на данном этапе обучения использует представление списка, в котором вы можете нажать на героя, чтобы увидеть подробности.
Маршрутизатор использует id
для отображения подробностей нужного героя.
Сначала импортируйте следующие члены в компонент, из которого вы хотите осуществлять навигацию.
1 2 3 |
|
Затем введите активированную службу маршрутизации:
1 |
|
Настройте класс так, чтобы у вас была наблюдаемая heroes$
, selectedId
для хранения id
номера героя, и герои в ngOnInit()
, добавьте следующий код для получения id
выбранного героя. Этот фрагмент кода предполагает, что у вас есть список героев, служба героев, функция для получения героев и HTML для отображения списка и деталей, как в примере Tour of Heroes.
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Затем в компоненте, на который вы хотите перейти, импортируйте следующие члены.
1 2 3 4 5 6 |
|
Вставьте ActivatedRoute
и Router
в конструктор класса компонента, чтобы они были доступны этому компоненту:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
Ленивая загрузка¶
Вы можете настроить свои маршруты на ленивую загрузку модулей, что означает, что Angular загружает модули только по мере необходимости, а не загружает все модули при запуске приложения. Кроме того, можно предварительно загружать части приложения в фоновом режиме, чтобы улучшить качество работы пользователя.
Более подробную информацию о ленивой загрузке и предварительной загрузке можно найти в специальном руководстве Ленивая загрузка NgModules.
Предотвращение несанкционированного доступа¶
Для предотвращения несанкционированного доступа пользователей к частям приложения используйте защитные экраны маршрутов. В Angular доступны следующие защиты маршрутов:
Чтобы использовать защиту маршрутов, используйте component-less routes, так как это облегчает защиту дочерних маршрутов.
Создайте файл для вашего охранника:
1 |
|
В файле guard добавьте функции guard, которые вы хотите использовать. В следующем примере для защиты маршрута используется canActivateFn
.
1 2 3 4 5 6 |
|
В модуле маршрутизации используйте соответствующее свойство в конфигурации routes
.
В данном случае canActivate
указывает маршрутизатору на необходимость посредничества в навигации по данному конкретному маршруту.
1 2 3 4 5 |
|
Более подробную информацию с рабочим примером можно найти в разделе учебника по маршрутизации, посвященном охранникам маршрутов.
Массив параметров ссылки¶
Массив параметров ссылки содержит следующие компоненты для навигации маршрутизатора:
- Путь маршрута к компоненту назначения
- Необходимые и необязательные параметры маршрута, которые входят в URL маршрута.
Привяжите директиву RouterLink
к такому массиву следующим образом:
1 |
|
Ниже представлен двухэлементный массив при указании параметра маршрута:
1 2 3 |
|
Предоставьте необязательные параметры маршрута в объекте, как в { foo: 'foo' }
:
1 |
|
Эти три примера покрывают потребности приложения с одним уровнем маршрутизации. Однако с дочерним маршрутизатором, как, например, в кризисном центре, вы создаете новые возможности массива ссылок.
Следующий минимальный пример RouterLink
основан на заданном дочернем маршруте по умолчанию для кризисного центра.
1 |
|
Рассмотрите следующее:
- Первый элемент массива идентифицирует родительский маршрут (
/crisis-center
). - Для этого родительского маршрута нет параметров
- Для дочернего маршрута нет параметров по умолчанию, поэтому вам нужно выбрать один из них.
- Вы переходите к
CrisisListComponent
, путь маршрута которого/
, но вам не нужно явно добавлять слеш.
Рассмотрим следующую ссылку маршрутизатора, которая ведет от корня приложения вниз к Кризису Дракона:
1 |
|
- Первый элемент массива идентифицирует родительский маршрут (
/crisis-center
). - Для этого родительского маршрута нет параметров
- Второй элемент идентифицирует дочерний маршрут подробностей о конкретном кризисе (
/:id
) - Для дочернего маршрута подробностей требуется параметр маршрута
id
. - Вы добавили
id
кризиса Дракона в качестве второго элемента массива (1
) - Получился путь
/crisis-center/1
.
Вы также можете переопределить шаблон AppComponent
исключительно с маршрутами Кризисного центра:
1 2 3 4 5 6 7 8 9 |
|
В целом, вы можете писать приложения с одним, двумя или более уровнями маршрутизации. Массив параметров ссылок позволяет гибко представлять любую глубину маршрутизации и любую законную последовательность маршрутных путей, (требуется) параметров маршрутизатора и (необязательно) объектов параметров маршрута.
LocationStrategy
и стили URL браузера¶
Когда маршрутизатор переходит к новому представлению компонента, он обновляет местоположение и историю браузера с URL для этого представления.
Современные браузеры HTML5 поддерживают history.pushState, технику, которая изменяет местоположение и историю браузера, не вызывая запрос страницы на сервере. Маршрутизатор может составить "естественный" URL, неотличимый от того, который в противном случае потребовал бы загрузки страницы.
Вот URL Кризисного центра в этом стиле "HTML5 pushState":
1 |
|
Старые браузеры отправляют запросы на сервер при изменении URL местоположения, если только изменение не происходит после "#" (называемого "хэшем"). Маршрутизаторы могут воспользоваться этим исключением, составляя URL маршрутов в приложении с помощью хэшей. Вот "хэш URL", который направляет в Кризисный центр.
1 |
|
Маршрутизатор поддерживает оба стиля с помощью двух провайдеров LocationStrategy
:
Провайдеры | Подробности |
---|---|
PathLocationStrategy | Стиль по умолчанию "HTML5 pushState". |
HashLocationStrategy | Стиль "хэш URL". |
Функция RouterModule.forRoot()
устанавливает LocationStrategy
в PathLocationStrategy
, что делает ее стратегией по умолчанию. У вас также есть возможность переключиться на HashLocationStrategy
с помощью переопределения во время процесса загрузки.
Более подробную информацию о провайдерах и процессе bootstrap смотрите в Dependency Injection.
Выбор стратегии маршрутизации¶
Вы должны выбрать стратегию маршрутизации на ранних этапах разработки проекта, потому что, как только приложение будет запущено в производство, посетители вашего сайта будут использовать и зависеть от ссылок URL приложения.
Почти все проекты Angular должны использовать стиль HTML5 по умолчанию. Он создает URL-адреса, которые легче понять пользователям, и сохраняет возможность рендеринга на стороне сервера.
Рендеринг критических страниц на сервере — это техника, которая может значительно улучшить воспринимаемую отзывчивость при первой загрузке приложения. Приложение, запуск которого в противном случае занял бы десять или более секунд, может быть отрисовано на сервере и доставлено на устройство пользователя менее чем за секунду.
Эта опция доступна только в том случае, если URL-адреса приложений выглядят как обычные веб-адреса без символов хэша (#
) в середине.
<base href>
¶
Маршрутизатор использует history.pushState браузера для навигации. pushState
позволяет настраивать пути URL в приложении; например, localhost:4200/crisis-center
.
URL-адреса внутри приложения могут быть неотличимы от URL-адресов сервера.
Современные браузеры HTML5 первыми стали поддерживать pushState
, поэтому многие называют эти URL "URL в стиле HTML5".
Навигация в стиле HTML5 является маршрутизатором по умолчанию. В разделе LocationStrategy и стили URL браузера вы узнаете, почему стиль HTML5 предпочтительнее, как настроить его поведение и как при необходимости переключиться на более старый стиль хэш (#
).
Вы должны добавить элемент <base href>
в index.html
приложения, чтобы маршрутизация pushState
работала. Браузер использует значение <base href>
для префиксации относительных URL при ссылке на файлы CSS, скрипты и изображения.
Добавьте элемент <base>
сразу после тега <head>
. Если папка app
является корнем приложения, как это сделано для данного приложения, установите значение href
в index.html
, как показано здесь.
1 |
|
HTML5 URLs и <base href>
¶
В последующих руководствах будут упоминаться различные части URL. На этой диаграмме показано, к чему относятся эти части:
1 2 3 4 |
|
Хотя маршрутизатор по умолчанию использует стиль HTML5 pushState, вы должны настроить эту стратегию с помощью <base href>
.
Предпочтительным способом настройки стратегии является добавление тега <base href>
element в <head>
в index.html
.
1 |
|
Без этого тега браузер не сможет загрузить ресурсы (изображения, CSS, скрипты) при "глубокой ссылке" в приложение.
Некоторые разработчики могут не иметь возможности добавить элемент <base>
, возможно, потому что у них нет доступа к <head>
или index.html
.
Такие разработчики все равно могут использовать HTML5 URL, выполнив следующие два шага:
-
Предоставьте маршрутизатору соответствующее значение
APP_BASE_HREF
. -
Используйте корневые URL (URL с
авторитетом
) для всех веб-ресурсов: CSS, изображений, скриптов и HTML-файлов шаблона.- Путь
<base href>
должен заканчиваться символом "/", так как браузеры игнорируют символы вpath
, следующие за крайним правым "/
". -
Если
<base href>
включает частьquery
, тоquery
используется только в том случае, еслиpath
ссылки на странице пуст и не содержитquery
.Это означает, что
query
в<base href>
включается только при использованииHashLocationStrategy
. -
Если ссылка на странице является корневым URL (имеет
авторитет
), то<base href>
не используется.Таким образом,
APP_BASE_HREF
с авторитетом приведет к тому, что все ссылки, созданные Angular, будут игнорировать значение<base href>
. -
Фрагмент в
<base href>
никогда не сохраняется.
- Путь
Для более полной информации о том, как <base href>
используется для построения целевых URI, смотрите раздел RFC о преобразовании ссылок.
HashLocationStrategy¶
Используйте HashLocationStrategy
, предоставив useHash: true
в объекте в качестве второго аргумента RouterModule.forRoot()
в AppModule
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|