Виктор Савкин - соучредитель nrwl.io, предоставляющий Angular консалтинг корпоративным командам. Ранее он входил в основную команду Angular в Google и создавал модули внедрения зависимостей, обнаружения изменений, форм и маршрутизатора.

Управление переходами между состояниями - одна из самых сложных частей при создании приложений. Это особенно актуально в Интернете, где вам также необходимо убедиться, что состояние отражается в URL-адресе. Кроме того, мы часто хотим разделить приложения на несколько пакетов и загружать их по запросу. Сделать это прозрачно - нетривиально.

Маршрутизатор Angular решает эти проблемы. Используя маршрутизатор, вы можете декларативно указывать состояния приложения, управлять переходами между состояниями, заботясь об URL-адресе, и загружать пакеты по запросу.

Эта статья основана на книге Angular Router, которую вы можете найти здесь https://leanpub.com/router. Книга выходит за рамки руководства по началу работы и подробно рассказывает о маршрутизаторе. Мысленная модель, ограничения дизайна и тонкости API - все покрыто. Если вам понравилась статья, загляните в книгу!

На следующей диаграмме показаны пять основных операций маршрутизатора Angular.

Маршрутизатор Angular принимает URL-адрес, затем:

1. Применяет перенаправления
2. Распознает состояния маршрутизатора
3. Запускает охрану и разрешает данные,
4. Активирует все необходимые компоненты
5. Управляет навигацией

Формат URL

Поскольку в приведенных ниже примерах я буду использовать много URL-адресов, давайте быстро рассмотрим формат URL.

/inbox/33(popup:compose)
/inbox/33;open=true/messages/44

Как видите, маршрутизатор использует круглые скобки для сериализации вторичных сегментов (например, popup: compose), синтаксис двоеточия для указания выхода и синтаксис '; параметр = значение' (например, open = true) для указания параметров конкретного маршрута. .

В приведенных ниже примерах мы предполагаем, что мы задали маршрутизатору следующую конфигурацию и переходим к «/ inbox / 33 / messages / 44».

Применение переадресации

Маршрутизатор получает URL-адрес от пользователя, когда он щелкает ссылку или обновляет адресную строку напрямую. Первое, что маршрутизатор делает с этим URL-адресом, - это применяет любые перенаправления.

Что такое редирект?

Редирект - это подмена сегмента URL. Перенаправления могут быть локальными или абсолютными. Локальные перенаправления заменяют один сегмент другим. Абсолютные перенаправления заменяют весь URL. Перенаправления являются локальными, если перед URL-адресом не стоит косая черта.

В предоставленной конфигурации есть только одно правило перенаправления: {path: ‘’, pathMatch: ‘full’, redirectTo: ‘/ inbox’}, т. Е. Замените ’/’ на ’/ inbox’. Это перенаправление является абсолютным, потому что значение redirectTo начинается с косой черты.

Поскольку мы переходим к «/ inbox / 33 / messages / 44», а не к «/», маршрутизатор не будет применять никаких перенаправлений, и URL останется без изменений.

Признающие государства

Затем маршрутизатор получит состояние маршрутизатора из URL-адреса. Чтобы понять, как работает этот этап, нам нужно немного узнать о том, как маршрутизатор сопоставляет URL-адрес.

Маршрутизатор проходит по массиву маршрутов один за другим, проверяя, начинается ли URL с пути маршрута. Здесь он проверит, что «/ inbox / 33 / messages / 44» начинается с «: папка». Поскольку это так, маршрутизатор установит параметр папки на «inbox», затем он возьмет дочерние элементы конфигурации, остальную часть URL-адреса «33 / messages / 44» и продолжит сопоставление. В результате параметр id будет установлен на «33», и, наконец, маршрут «messages /: id» будет сопоставлен со вторым параметром id, установленным на «44».

Если путь, пройденный через конфигурацию, не «потребляет» весь URL-адрес, маршрутизатор возвращается к альтернативному пути. Если невозможно сопоставить весь URL-адрес, навигация не выполняется. Но если это сработает, будет построено состояние маршрутизатора, представляющее будущее состояние приложения.

Состояние маршрутизатора состоит из активированных маршрутов. И каждый активированный маршрут может быть связан с компонентом. Также обратите внимание, что у нас всегда есть активированный маршрут, связанный с корневым компонентом приложения.

Бегущие охранники

На этом этапе у нас есть будущее состояние маршрутизатора. Затем маршрутизатор проверит, разрешен ли переход в новое состояние. Он сделает это с помощью охранников. Мы подробно рассмотрим охранников в следующих статьях. На данный момент достаточно сказать, что защита - это функция, которую выполняет маршрутизатор, чтобы убедиться, что переход к определенному URL-адресу разрешен.

Разрешение данных

После того, как маршрутизатор запустит охрану, он разрешит данные. Чтобы увидеть, как это работает, давайте настроим нашу конфигурацию сверху.

Где ConversationsResolver определяется следующим образом:

Наконец, нам нужно зарегистрировать ConversationsResolver при загрузке нашего приложения.

Теперь при переходе в папку «/ inbox» маршрутизатор создаст состояние маршрутизатора с активированным маршрутом для компонента разговоров. Для этого маршрута параметр папки будет установлен на «входящие». Используя этот параметр с текущим пользователем, мы можем получить все беседы из почтового ящика для этого пользователя.

Мы можем получить доступ к разрешенным данным, внедрив активированный объект маршрута в компонент разговоров.

Активация компонентов

На данный момент у нас есть состояние маршрутизатора. Теперь маршрутизатор может активировать это состояние, создав экземпляры всех необходимых компонентов и поместив их в соответствующие розетки маршрутизатора.

Чтобы понять, как это работает, давайте посмотрим, как мы используем розетки маршрутизатора в шаблоне компонента.

У корневого компонента нашего приложения есть два выхода: основной и всплывающий.

Другие компоненты, такие как ConversationCmp, имеют только один.

Теперь представьте, что мы переходим к «/ inbox / 33 / messages / 44 (popup: compose)».

Вот что сделает роутер. Во-первых, он создаст экземпляр ConversationCmp и поместит его в основной выход корневого компонента. Затем он поместит новый экземпляр ComposeCmp во всплывающее окно. Наконец, он создаст новый экземпляр MessageCmp и поместит его в основной выход только что созданного компонента диалога.

Использование параметров

Часто компоненты полагаются на параметры или разрешенные данные. Например, компонент диалога, вероятно, должен получить доступ к объекту диалога. Мы можем получить параметры и данные, внедрив ActivatedRoute.

Если мы перейдем от «/ inbox / 33 / messages / 44 (popup: compose)» к

‘/ Inbox / 34 / messages / 45 (popup: compose)’, наблюдаемые данные выдадут новую карту с новым объектом, а компонент беседы отобразит информацию о беседе 34.

Как видите, маршрутизатор предоставляет параметры и данные как наблюдаемые, что удобно в большинстве случаев, но не всегда. Иногда нам нужен снимок состояния, который мы можем сразу изучить.

Навигация

Итак, на этом этапе маршрутизатор создал состояние маршрутизатора и создал экземпляры компонентов. Затем нам нужно иметь возможность переходить из этого состояния маршрутизатора в другое. Это можно сделать двумя способами: императивно, вызвав router.navigate, или декларативно, используя директиву RouterLink.

Императивная навигация

Для обязательной навигации введите службу маршрутизатора и вызовите навигацию.

RouterLink

Другой способ навигации - использование директивы RouterLink.

Эта директива также обновит атрибут href при применении к элементу ссылки «‹a›«, поэтому он удобен для SEO, и поведение открытия вкладки в новом браузере при щелчке правой кнопкой мыши, которое мы ожидаем от обычных ссылок, будет работать.

Резюме

Давайте еще раз рассмотрим все операции роутера Angular.

Когда браузер загружает «/ inbox / 33 / messages / 44 (popup: compose)», маршрутизатор будет делать следующее. Во-первых, он применит перенаправления. В этом примере ни один из них не будет применен, а URL останется как есть. Затем маршрутизатор будет использовать этот URL-адрес для создания нового состояния маршрутизатора.

Затем маршрутизатор создаст экземпляры компонентов диалога и сообщения.

Теперь предположим, что компонент сообщения имеет следующую ссылку в своем шаблоне:

<a [routerLink]=”
  ['/', {outlets: {popup: [‘message’, this.id]}}]”>Edit</a>

Директива ссылки маршрутизатора примет массив и установит для атрибута href значение

«/ Inbox / 33 / messages / 44 (всплывающее окно: сообщение / 44)».

Теперь пользователь запускает навигацию, щелкая ссылку. Маршрутизатор возьмет созданный URL-адрес и запустит процесс заново: он обнаружит, что компоненты диалога и сообщения уже на месте. Так что никакой работы там не нужно. Но он создаст экземпляр PopupMessageCmp и поместит его во всплывающее окно. Как только это будет сделано, маршрутизатор обновит свойство местоположения новым URL-адресом.

Это было интенсивно - много информации! Но мы узнали довольно много вещей. Мы узнали об основных операциях маршрутизатора Angular: применении перенаправлений, распознавании состояния, запуске охранников и разрешении данных, активации компонентов и навигации. Наконец, мы рассмотрели пример e2e, показывающий маршрутизатор в действии.

Виктор Савкин - соучредитель Nrwl. Мы помогаем компаниям развиваться, как Google, с 2016 года. Мы предоставляем консультации, инжиниринг и инструменты.

Если вам это понравилось, нажмите 👏 ниже, чтобы другие люди увидели это здесь, на Medium. Подпишитесь на @victorsavkin, чтобы узнать больше о монорепозиториях, Nx, Angular и React.