Перевод: Angular 2 Router Introduction — Child Routes, Auxiliary Routes, Avoid Common Pitfalls

В этой статье мы опишем новый реактивный роутинг Angular 2. Во избежания недоразумений это статья о новой версии 3.0 компонента роутинга а не о @angular/router-deprecated.

Мы собираем рассказать о следующем:

  • Почему сегодня не используется везде одностраничные приложения (Single Page Apps), and и почему это может поменятся
  • Начальная настройка роутинга, избегаем типичных ловушек
  • Настройка домашнего и запасного маршрута, почему порядок важен
  • Навигация между маршрутами используя routerLink
  • Master Detail с дочерними маршрутами (Child Routes) — как дочерние маршруты работают?
  • Понятия Route Snapshot и Router Snapshot
  • Вспомогательные маршруты (Auxiliary Routes): что это и когда их использовать?
  • Заключение

Почему везде не используются одностраничные приложения ?

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

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

Почему одностраничные приложения могут быть идеальны для интернета?

Для приложений с аутентификацией таких как Gmail обычно нормально подождать 6 секунд для загрузки. В отличие от публичного интернета, где производительность и пользовательское удобство главное достоинство одна дополнительная секунда (или даже 200ms) загрузки страницы и его стоимость.

Представте сайт такой как Amazon как одностраничное приложение: если бы могли переходить между страницами без полной перезагрузки страницы это бы значительно уменьшело бы отказы от ожидания загрузки страниц.

Почему одностраничные приложения могут стать более предпочтительные в будущем ?

Но для разработчиков Angular 2 есть хорошие новости, и разработчиков одностраничных приложений в общем: паук Google сейчас намного лучше понимают одностраничные приложения.

Это значит что одностраничные приложения сегодня более привлекательны чем когда либо, и их популярность будет только расти. Давайте посмотрим как создавать такие приложения с помощью Angular 2 Router.

Конфигурирования Angular 2 Router

Первая вещь которую мы должны сделать это написать конфигурацию роутинга. То есть сопоставить каждый url с компонентами которые будут их отрабатывать.

Пример конфигурации RouteConfig с парой простых маршрутов:

Это простая конфигурация означает: если мы перейдем по ссылке /home то отобразится компонент Home; если мы перейдем /lessons то отобразится компонент AllLessons. И если вы перейдете по любому другому url то отобразится ошибка.

Но где отображаются компоненты?

Конфигурирование основного (primary) места для отображения

Как только будет переход по ссылке, роутер отобразит соотвествующий компонент. Для этого он будет ожидать наличие в своем шаблоне тега router-outlet:

 

Начальная загрузка роутера

Для завершения конфигурирования роутера нам так же нужно добавить его директивы в систему начальной загрузки Angular 2. Для этого мы импортируем RouterModule в корневой модуль:

Обратите внимание на использование функции forRoot вместо простого добавления RouterModule. Прочитать  об этом подробнее @NgModule.

Теперь если мы перейдем по ссылке /home или /lessons, отобразится соотвествующий компонент.

Так же нужно еще добавить базовый URL в index.html

Здесь для новичков скрывается одна из возможных ловушек.

Что может пойти не так как подразумевается?

С текущей конфигурацией, если мы будем переходить по ссылкам с главной страницы используя встроенный механизм роутинга, то все будет работать как надо, но если мы попытаемся набрать url в строке браузера для прямого перехода на /lessons, мы получим ошибку 404 страница не найдена. Почему так?

Описание проблемы

Первое что нужно знать о новом роутинге в Angular 2 это то что он по умолчанию использует HTML5 History API. Это означает что роутинг больше не использует # как часть url. В версии Angular 1 # использовался для прямого перехода между страницами.

Это означает что когда происходит переход на /lessons, то именно этот url и отображает в адресной строке браузера, в отличие от старой версии где отобразился бы такой url /#/lessons .

Для чего использовался # в навигации

В старой версии url был корневой точкой приложения, поэтому когда происходило обновление страницы то обновлялся index.html. А все что было после # игнориловалось.

Сейчас, при попытки загрузить файл lessons, будет ошибка (404 Not found) так как ожидается наличие такой странице на сервере а такой страницы не существует .

Как избежать 404 not found в новом роутинге ?

Для этого вам обязательно нужно сконфигурировать ваш сервер с url по умолчанию, то есть в случае если не найдена страница то был бы переход на index.html, в нашем примере при переходе на /lessons мы бы получали бы index.html а не 404 Not found.

Такое конфигурирование зависит от той серверной технологии которую вы используете. В случае использования Node в качестве сервера и Express в качестве серверного фреймворка. Нам нужно добавить в конфигурацию Node следующее:

 

Настройка маршрута по умолчанию и резервного (fallback) маршрута, почему порядок важен?

Новый компонент роутинга поддерживает нотации пустого пути и wildcards, что означает что мы можем сконфигурировать маршрут по умолчанию и запасной (fallback) маршрут:

Мы можем видеть что маршрут по умолчанию привязывается url / с компонентом Home, все другие маршруты к компоненту PageNotFoundComponent. Но тут есть один нюанс.

Почему порядок важен

Одна из ключевых вещей в конфигурирование роутинга это то что порядок маршрутов имеет большое значение. Когда роутер получает url, он начинает искать совпадение по всем маршрутам в порядке указаном в конфигурации: начиная с первого элемента.

В случае если он находит совпадение, поиск останавливается и инициируется соотвествующий компонент. Поэтому если мы укажем первым запасной (fallback) маршрут (**), каждый url будет совпадать с ним ** и роутинг будет остановлен на нем.

Вот почему запасной маршрут всегда должен быть последним. Настроим переходы между маршрутами. Есть два варианта как это сделать:

  • создать шаблон с директивами навигации routerLink
  • программным способом с помощью Router API

Router навигация с директивой routerLink

Так как мы включили RouterModule в наше приложение, то мы можем использовать директиву routerLink. Примеры вариантов использования:

Мы можем указать url в шаблоне напрямую. Но так же можем использовать функцию перехода.

Программная навигация

Используем для этого методы navigate или navigateByUrl:

Одна из самых часто используемых вещей при навигации это передача параметров.

Параметры навигации — Избегаем утечки памяти

Если нам будет нужно передовать параметры между маршрутами, то нам нужно использовать объект observable который предоставляет Router API. Для примера когда нам нужно перейти на определеный курс используя url /courses/1 (где 1 это Id курса), то так же нам нужно будет получать id курс из url:

Мы может видеть что observables позволяет нам отслеживать изменения маршрута и реагировать на это. Один важный момент при навигации это необходимость предотвращать утечки памяти.

Взгляните на урок Exiting an Angular 2 Route — How To Prevent Memory Leaks для получение больше информации.

Понятия Route Snapshot и Router Snapshot

Одно из ключевых свойств нового роутинга это его реактивность. Это означает что API предоставляет несколько объектов observables на которые можно подписаться что бы реагировать на изменения в роутинге.

Иногда нам не нужно получать последнее значени маршрута или его параметров иногда нам нужно значение которое было в момент инициализации компонента

Для этого роутер представляет snapshot. Snapshot может быть внедрен в конструктор компонента:

С этими snapshots мы получаем параметры роутинга в момент навигации.

Зачем нам нужны snapshot целого роутера ?

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

Реализация Master Detail используя дочерние маршруты

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

Это звучит так как устроенно в нашем примере. Только /home или /lessons может быть активно в текущем моменте. Соотвественно мы можем переписать нашу конфигурацию используя дочерние маршруты:

Это даст нам точно такой же результат как был до этого: только /home или /lessons может быть активно в один момент времени. Помните что конфиг роутинга может иметь только один тег router-outlet, то есть в конце концов отобразиться только один компонент.

Использование дочерних маршрутов для реализации Master Detail

Одно из применения дочерних маршрутов это реализация UI шаблона Master Detail.

Представьте себе курс со списком уроков. Вам нужно кликнуть на урок в списке для перехода на него. Но здесь может быть проблема, могут быть несколько типов уроков: видео уроки, текстовые лекции, упражнения и т.п..

Один из путей решения этой проблемы это использование дочерних маршрутов:

Это один из способов реализации этого шаблона.

Когда пользователь выбирает один из уроков в зависимости от выбранного урока будет выбран соотвествющий компонент CourseLessons.

Вспомогательные маршруты: что это и для чего их используют?

Что же такое вспомогательыне маршруты? Это такие маршруты которые как и основные маршруты мапируются с router-outlet. Но в отличие от основных они мапируются к другому outlet которому нужно назначить имя.

Далее пример страницы с несколькими outlet:

Практическое использование вспомогательных маршрутов

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

Типичный пример это приложения с разными секциями на страницы:

  • меню верхнего уровня
  • боковое меню которое часто зависит от верхнего меню
  • боковое меню справа может к примеру отображать список уроков
  • всплывающие диалоги для редактирования деталей, которые иммеют отношения к навигации
  • окно чата открытое в течение навигации

Пример конфигурировнаия вспомагательных маршрутов

Представте что справа экрана у нас будет список уроков:

Как же выглядят url для впомогательных маршрутов?

Angular 2 Router имеет специальный синтаксис для определения вспомогательных url. Например для перехода на AllLessons в основном outlet и Playlist в rightAside outlet. Ссылка будет выглядеть так:

/lessons(aside:playlist)

/lessons будет все еще основным маршрутом компонента AllLessons. Но внутри будет вспомогательный маршрут aside.

Затем идет двоиточье и потом у нас есть url которые применяется к outlet, в нашем случае /playlist. В этом случае компонент Playlist будет отображен в outlet aside.

Обратите внимание что у вас могут быть несколько вспомогательных маршрутов внутри скобок разделенных //. Для примера:

Хороший пример использоваия вспомогательных маршрутов

Завершение

Новый реактивный роутер Angular 2 содержит новые супер полезные свойства. В этой статье мы описали некоторые из базовых концепций с примерами: начальное конфигурирование, навигация, дочерние и вспомогательные маршруты.

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

It's only fair to share...Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedInShare on VK