Введение в angular

Содержание:

Организация кода

Избавляемся от громоздких выражений в

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

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

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

С этими изменениями достаточно просто управлять подключаемыми модулями:

В данном примере импорт производится напрямую из вместо громоздкого выражения (например ). Это возможно благодаря ре-экспорту публичных компонентов в основном файле . Желательно создать файл на каждый пакет в котором нужно произвести реэкспорт всех публичных модулей:

Core, Shared и Feature модули

Для более гибкого управления составными частями приложения довольно часто в литературе и различных интернет ресурсах рекомендуют разносить видимость его компонентов. В этом случае управление составными частями приложения упрощается. Наиболее часто используется следующее разделение: Core, Shared и Feature модули.

CoreModule

Основное предназначение CoreModule — описание сервисов, которые будут иметь один экземпляр на все приложение (т.е. реализуют паттерн синглтон). К таким часто относятся сервис авторизации или сервис для получения информации о пользователе. Пример CoreModule:

SharedModule

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

FeatureModule

Здесь можно повторить Angular style guide. Для каждой независимой функции приложения создается отдельный FeatureModule. FeatureModule должны импортировать сервисы только из . Если некоторому модулю понадобилось импортировать сервис из другого модуля, возможно, этот сервис необходимо вынести в .

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

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

  1. https://github.com/ngrx/store
  2. http://stepansuvorov.com/blog/2017/06/angular-rxjs-unsubscribe-or-not-unsubscribe/
  3. https://medium.com/@tomastrajan/6-best-practices-pro-tips-for-angular-cli-better-developer-experience-7b328bc9db81
  4. https://habr.com/post/336280/
  5. https://angular.io/docs

Кто поддерживает Angular?

Angular Core Team состоит из большого количества людей во всем мире и из сообщества Angular. При этом большая часть разработок Angular изо дня в день осуществляется сотрудниками Google. Примерно 20 сотрудников Google входят в Angular Core Team и все ТОП-разработчики проекта Angular являются сотрудниками Google.

Следует отметить, что, несмотря на контроль Google над Angular, сам фреймворк по-прежнему много в чём зависит от усилий сообщества. Более двух тысяч человек внесли свой вклад в open-source репозиторий Angular, в общем доступе есть бесчисленные туториалы и guides, многочисленные компании предлагают обучение и набор инструментов для разработчиков.

Если контроль над проектом принадлежит одной компании, это неплохо, так как снижает конфликтные вопросы при принятия нестандартных решений.

… и недостатки

  • У , конечно, есть кривая обучения. Не большая, но и не такая маленькая, и я думаю, что это требует некоторого опыта или глубокого понимания некоторых программных шаблонов. Это не является проблемой для любого разработчик среднего уровня, но младший может поначалу немного запутаться.
  • Для меня это ощущается немного многословно (прим пер.: речь о проблеме множества заготовок кода — ). Поэтому каждый раз, когда вы добавляете какое-либо свойство в состояние (), вам нужно добавлять действия () и диспетчеры (). Вам может потребоваться обновить или добавить селекторы (), эффекты (), если таковые имеются, и обновить хранилище (). Кроме того, вы будете собирать конвейер () операторов и наблюдаемых потоков () везде где это потребуется.
  • не является частью библиотек , и не поддерживается Google. По крайней мере, не напрямую, потому что среди контрибьюторов есть разработчики из команды . Это ещё один пункт для обдумывания — вы добавляете в зависимости тяжёлую библиотеку.

Единый источник правды

Для архитектуры redux и ngrx это означает, что состояние всего вашего приложения хранится в древовидном объекте, — в одном хранилище.

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

Когда вы создаете приложение angular, вы обычно разделяете состояние, и обрабатываете их в разных сервисах. По мере того как ваше приложение растёт, отслеживание изменения состояний становится беспорядочным, их трудно отлаживать и поддерживать. Наличие единственного источника правды решает эту проблему, поскольку состояние обрабатывается только в одном объекте и в одном месте, поэтому отладка или добавление изменений становится намного проще.

Пример использования NGRX

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

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

Вот что это будет:

  • Установить библиотеки
  • Создать структуру папок для хранилища
  • Создать состояние и начальные значения
  • Создать действия
  • Создать редукторы
  • Создать эффекты
  • Создать селекторы
  • Собрать и настроить всё вместе
  • Использовать хранилище в некоторых компонентах

Итак, приступим …

Отлично … так каковы же преимущества использования NGRX

Мы уже упоминали большинство из них, когда говорили о принципах шаблона . Но давайте отметим наиболее важные преимущества использования шаблона в приложении (на взгляд автора):

  • Поскольку у нас есть один источник правды, и вы не можете напрямую изменить состояние, приложения будут работать более согласованно.
  • Использование шаблона дает нам много интересных функций (), облегчающих отладку.
  • Тестирование приложений становится проще, поскольку мы вводим чистые функции для обработки изменений состояния, а также потому, что и , и , имеют множество замечательных возможностей для тестирования.
  • Как только вы почувствуете себя комфортно при использовании , понимание потока данных в ваших приложениях станет невероятно простым и предсказуемым.

Какую версию Angular мне лучше использовать?

На данный момент существует две популярные версии Angular. Версия 1 доступна на https://angularjs.org/  и является обновлённой версией того Angular, что был представлен Miško и его командой в 2011 году. Другая популярная версия теперь называется просто Angular и доступна на https://angular.io/. Современный Angular – это полностью переделанная версия для новых браузеров, рабочих процессов и платформ разработки.

Почти во всех случаях вам следует придерживаться последней версии Angular. В ближайшем будущем команда Angular будет стремиться поддерживать Angular 1, но нет никаких оснований полагать, что они будут поддерживать и более старые версии. Более того, Angular 1 не допускает использования библиотеки вне браузера, поэтому вы не можете воспользоваться такими библиотеками, как NativeScript для создания мобильных приложений.

Изменения делаются чистыми функциями

Операция, инициируемая отправкой действия, будет чистой функцией, называемой в архитектуре — (редукторами).

Эти редукторы (просто чистые функции) получают действие () и состояние (), в зависимости от отправленного действия (обычно отфильтрованного оператором ), они выполняют операцию и возвращают новый объект состояния.

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

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

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

AngularJS Directives

As you have already seen, AngularJS directives are HTML attributes with an ng prefix.

The ng-init directive initializes AngularJS application variables.

AngularJS Example

<div ng-app=»» ng-init=»firstName=’John'»>
<p>The name is <span ng-bind=»firstName»></span></p>
</div>

Alternatively with valid HTML:

AngularJS Example

<div data-ng-app=»» data-ng-init=»firstName=’John'»>
<p>The name is <span data-ng-bind=»firstName»></span></p>
</div>

You can use data-ng-, instead of ng-, if
you want to make your page HTML valid.

You will learn a lot more about directives later in this tutorial.

Как устроен Angular: компоненты

Angular-приложения состо­ят из неза­ви­си­мых эле­мен­тов. Эти эле­мен­ты назы­ва­ют­ся ком­по­нен­та­ми, и у каж­до­го ком­по­нен­та своё поведение. 

Напри­мер, лен­та ново­стей — один ком­по­нент. Отве­ча­ет за отоб­ра­же­ние спис­ка ново­стей на стра­ни­це. Кноп­ка «Про­чи­тать» — дру­гой ком­по­нент. Отве­ча­ет за пере­ход со стра­ни­цы спис­ка ново­стей к выбран­ной новости. 

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

Ком­по­нен­ты под­чи­ня­ют­ся жиз­нен­ным цик­лам — меня­ют­ся и рабо­та­ют по несколь­ким запро­грам­ми­ро­ван­ным сце­на­ри­ям. Возь­мём ситу­а­цию, когда мы пере­хо­дим со стра­ни­цы спис­ка ново­стей к одной ново­сти. В этом слу­чае ком­по­нент «Лен­та ново­стей» уни­что­жа­ет­ся и при необ­хо­ди­мо­сти созда­ёт­ся повтор­но. Жиз­нен­ные цик­лы раз­гру­жа­ют память и уско­ря­ют приложение.

Стра­ни­ца с шап­кой, лен­той ново­стей и тре­мя кноп­ка­ми. Каж­дый эле­мент — неза­ви­си­мый ком­по­нент, кото­рый выпол­ня­ет какое-то дей­ствие внут­ри приложения 

Google ненавидит SPA

Когда мы говорим про современные интернет магазины, мы представляем себе тяжелые для понимания серверы, рендрящие тысячи статических страничек. Причем именно эти тысячи отрендеренных страниц одна из причин, почему Single Page Applications не прижились в электронной коммерции. Даже крупнейшие магазины электронной коммерции по-прежнему выглядят как куча статических страниц. Для пользователя это нескончаемый цикл кликов, ожиданий и перезагрузки страниц.

Одностраничные приложения приятно отличаются динамичностью взаимодействия с пользователем и более сложным UX. Но как не прискорбно обычно пользовательский комфорт приносится в жертву SEO оптимизации. Для сеошника сайт на angular – это своего рода проблема, поскольку поисковикам трудно индексировать страницы с динамическим контентом.

Мы любим JS и Angular. Мы верим, что классный и удобный UX может быть построен на этом стеке технологий, и мы можем решить все сопутствующие проблемы. В какой-то момент мы столкнулись с . Это модуль для рендеринга на стороне сервера. Сначала нам показалось, вот оно – решение! Но радость была преждевременной — и отсутствие больших проектов с его применением тому доказательство.

Добавление нового состояния

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

Состояние может быть исходным и производным. Исходное состояние — это независимые данные, которые существуют сами по себе (например, состояние входа в систему). Производное состояние полностью зависит от фрагмента исходного (например, текстовое уведомление с надписью «Войдите в систему», если пользователь вышел из нее, или наоборот). Это текстовое значение не нужно хранить где-либо. При необходимости его можно рассчитать на основе состояния аутентификации. Таким образом, следующий фрагмент кода:

… можно преобразовать в этот:

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

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

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

Настроить всё вместе

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

Давайте посмотрим модуль приложения:

Файл с описанием модуля приложения

Давайте перечислим то, что необходимо для настройки нашего хранилища:

  1. Мы импортируем наши редукторы, и передаём их в метод модуля хранилища.
  2. Мы импортируем наши эффекты, и передаём их внутри массива в метод модуля эффектов.
  3. Мы передаём настройки для модуля состояния маршрутизатора .
  4. И мы добавляем инструменты разработчика хранилища , если запущена среда разработки.

Первые два шага необходимы, в то время как шаги 3 и 4 я настоятельно рекомендую, но они не являются обязательными.

Теперь мы наконец закончили … и можем использовать хранилище в наших компонентах!

Подводные камни Angular Universal

Не трогайте DOM

Когда мы начали тестировать компоненты нашего магазина с помощью , нам пришлось потратить некоторое время, чтобы понять, почему наш сервер падает при запуске без вывода серверной страницы. Например, у нас есть компонент Session Flow component, который отслеживает активность пользователя во время сессии (перемещения пользователя, клики, рефферер, информация об устройстве пользователя и т.д.). После поиска информации в issues на мы поняли, что в нет обертки над DOM.

.

Если вы склонируете этот Angular Universal стартер и откроете browser.module.ts вы увидите, что в массиве разработчики Universal предоставляют два:

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

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

Если вы хотите активно взаимодействовать с элементами DOM, используйте сервисы API, такие как, или .

Правильный роутинг

Поскольку сервер отражает наше приложение, у нас была проблема с роутингом.

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

Тогда нужно создать файл с массивом роутов сервера. Корневой маршрут можно не добавлять:

Наконец, добавьте роуты на сервер:

Пререндеринг стартовой страницы

Одной из наиболее важных особенностей является пререндеринг. Из исследования Kissmetrics следует, что 47% потребителей ожидают, что веб-страница загрузится за 2 секунды или даже менее

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

Давайте подробнее рассмотрим, что это такое и как его использовать.

Когда пользователь открывает URL нашего магазина, немедленно возвращает предварительно подготовленную HTML страничку с контентом, а уже затем затем начинает загружать все приложение в фоновом режиме. Как только приложение полностью загрузится, подменяет изначальную страницу нашим приложением. Вы спросите, что будет, если пользователь начнет взаимодействовать со страницей до загрузки приложения? Не беспокойтесь, библиотека Preboot.js запишет все события, которые выполнит пользователь и после загрузки приложения выполнит их уже в приложении.

Чтобы включить пререндеринг, просто добавьте в конфигурацию сервера :

Добавление мета-тегов

В случае SEO-ориентированного сайта добавление мета-тегов очень важно. Например, у нас есть , который представляет страницу определенного продукта

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

Команда создала сервис angular2-meta, чтобы легко манипулировать мета-тегами. Вставьте мета-сервис в ваш компонент и несколько строк кода добавлят мета-теги в вашу страницу:

В следующей версии Angular этот сервис будет перемещен в@angular/platform-server

Кэширование данных

запускает ваш XHR запрос дважды: один на сервере, а другой при загрузке приложения магазина.

Но зачем нам нужно запрашивать данные на сервере дважды? PatricJs создал пример, как сделать Http-запрос на сервере один раз и закэшировать полученные данные для клиента. Посмотреть исходный код примера можно . Чтобы использовать его заинжекте и вызовите метод для выполнения http-вызовов с кешированием:

История разработки [ править | править код ]

AngularJS разработан в 2009 году Мишко Хевери и Адамом Абронсом в Brat Tech LLC как программное обеспечение позади сервиса хранения JSON-данных, измеряющихся мегабайтами, для облегчения разработки корпоративных приложений. Сервис располагался на домене «GetAngular.com» и имел нескольких зарегистрированных пользователей, прежде чем они решили отказаться от идеи бизнеса и выпустить Angular как библиотеку с открытым исходным кодом.

Абронс покинул проект, но Хевери, работающий в Google, продолжает развивать и поддерживать библиотеку с другими сотрудниками Google Игорем Минаром и Войта Джином.

В марте 2014 было объявлено о начале разработки AngularJS 2.0 . Новая версия писалась с нуля на TypeScript и очень сильно отличалась от предыдущей, поэтому позже было решено развивать её как отдельный фреймворк с названием Angular. Angular 2 был выпущен 15 сентября 2016 года , тогда как первая версия продолжила развиваться отдельно как AngularJS.

Работа с pipes

Последнее обновление: 16.05.2021

Pipes представляют специальные инструменты, которые позволяют форматировать отображаемые значения. Например, нам надо вывести определенную дату:

import { Component} from '@angular/core';
      
@Component({
    selector: 'my-app',
    template: `<div>Без форматирования: `myDate`</div>
			   <div>С форматированием: {{myDate | date}}</div>`
})
export class AppComponent { 

	myDate = new Date(1961, 3, 12);
}

Здесь создается дата, которая дважды выводится в шаблоне. Во втором случае к дате применяется форматирование с помощью класса DatePipe.

Встроенные pipes

В Angular есть ряд встроенных pipes. Основные из них:

  • CurrencyPipe: форматирует валюту

  • PercentPipe: форматирует проценты

  • UpperCasePipe: переводит строку в верхний регистр

  • LowerCasePipe: переводит строку в нижний регистр

  • DatePipe: форматирует дату

  • DecimalPipe: задает формат числа

  • SlicePipe: обрезает строку

При применении классов суффикс отбрасывается (за исключением DecimalPipe — для его применения используется название «number»):

import { Component} from '@angular/core';
      
@Component({
    selector: 'my-app',
    template: `<div>{{welcome | uppercase}}</div>
			   <div>{{welcome | lowercase}}</div>
			   <div>{{persentage | percent}}</div>
			   <div>{{persentage | currency}}</div>`
})
export class AppComponent { 

	welcome: string = "Hello World!";
	persentage: number = 0.14; 
}

Параметры в pipes

Pipes могут получать параметры. Например, пайп SlicePipe, который обрезает строку, может получать в качестве параметра, начальный и конечный индексы подстроки,
которую надо вырезать:

import { Component} from '@angular/core';
      
@Component({
    selector: 'my-app',
    template: `<div>{{welcome | slice:3}}</div>
			   <div>{{welcome | slice:6:11}}</div>`
})
export class AppComponent { 

	welcome: string = "Hello World!";
}

Все параметры в пайп передаются через двоеточие. В данном случае вырезает подстроку, начиная с 6 до 11 индекса. При этом,
если начала выреза строки обязательно передавать, то конечный индекс необязателен. В этом случае в качестве конечного индекса выступает конец строки.

Форматирование дат

DatePipe в качестве параметра может принимать шаблон даты:

import { Component} from '@angular/core';
      
@Component({
    selector: 'my-app',
    template: `<div>{{myDate | date:"dd/MM/yyyy"}}</div>`
})
export class AppComponent { 

	myDate = Date.now();
}

Форматирование чисел

DecimalPipe в качестве параметра принимает формат числа в виде шаблона:

{{ value | number  ] }}
  • : само выводимое значение

  • : строка в формате «minIntegerDigits.minFractionDigits-maxFractionDigits», где

    • — минимальное количество цифр в целой части

    • — минимальное количество цифр в дробной части

    • — максимальное количество цифр в дробной части

  • : код применяемой культуры

import { Component} from '@angular/core';
      
@Component({
    selector: 'my-app',
    template: `<div>{{pi | number:'2.1-2'}}</div>
	<div>{{pi | number:'3.5-5'}}</div>`
})
export class AppComponent { 

	pi: number = 3.1415;
}

Форматирование валюты

CurrencyPipe может принимать ряд параметров:

{{ value | currency  ] ] ] }}
  • : выводимая сумма

  • : код валюты согласно спецификации ISO 4217. Если не указан, то по умолчанию применяется USD

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

    • : отображает код валюты (например, USD)

    • (значение по умолчанию): отображает символ валюты (например, $)

    • : некоторые страны используют в качестве символа валюты несколько символов, например, канадский доллар — CA$, данный параметр
      позволяет получить собственно символ валюты — $

    • : отображает произвольную строку

  • : формат числа, который применяется в DecimalPipe

  • : код используемой локали

Цепочки pipes

Вполне возможно, что мы захотим применить сразу несколько pipes к одному значению, тогда мы можем составлять цепочки выражений, разделенные вертикальной чертой:

import { Component} from '@angular/core';
      
@Component({
    selector: 'my-app',
    template: `<div>{{message | slice:6:11 | uppercase}}</div>`
})
export class AppComponent { 

	message = "Hello World!";
}

НазадВперед

Как изучить Angular

Angular — это фрейм­ворк для опыт­ных фронтенд-разработчиков. Его не изу­ча­ют на кур­сах про­грам­ми­ро­ва­ния с нуля, пото­му что для ком­мер­че­ской раз­ра­бот­ки нуж­ные общие знания: 

  1. HTML, CSS, JavaScript — база для запус­ка сайта. 
  2. TypeScript — реко­мен­до­ван­ный язык для Angular-приложений. 
  3. Git и GitHub — инстру­мен­ты хра­не­ния кода и команд­ной работы. 
  4. Пакет­ные мене­дже­ры — тех­но­ло­гия уста­нов­ки про­грамм и обновлений. 
  5. Пре­про­цес­со­ры — син­так­сис для упро­щён­но­го напи­са­ния кода. 

Тре­бо­ва­ния к Angular-разработчикам пери­о­ди­че­ски обнов­ля­ют­ся и пуб­ли­ку­ют­ся на roadmap.sh. Ещё мы реко­мен­ду­ем посе­тить madewithangular.com — это сайт с переч­нем при­ло­же­ний и сер­ви­сов на Angular. Если не понра­вит­ся резуль­тат, то вы не потра­ти­те вре­мя и выбе­ре­те для обу­че­ния дру­гой фрейм­ворк — React или Vue.

Кар­та навы­ков фронтенд-разработчика в 2021 году. Если хоти­те изу­чить Angular — при­дёт­ся осво­ить боль­ше поло­ви­ны обя­за­тель­ных технологий 

Пример NGRX

  1. Установка библиотеки
  2. Создание структуры папок для хранилища
  3. Создание хранилища и начальных значений
  4. Создание действий (Actions)
  5. Создание редукторов (Reducers)
  6. Создание эффектов (Effects)
  7. Создание селекторов (Selectors)
  8. Конечная настройка
  9. Использование хранилища в компонентах

Создание хранилища и начальных значений

  1. Мы создаем и экспортируем интерфейс со структурой пользовательской среды.
  2. Мы делаем то же самое с начальным пользовательским состоянием, которое реализует недавно созданный интерфейс.
  1. Состояние приложения содержит состояние пользователя и конфигурации, а также состояние маршрутизатора.
  2. Потом задаем начальное состояние приложения.
  3. Наконец, экспортирует функцию, чтобы получить начальное состояние (мы будем использовать его позже).

Создание Действий

  1. Мы экспортируем Enum, содержащий определение для типов действий. Таким образом, мы избегаем использования и повторения строк для использования типов действий, процесс, который может легко порождаться ошибками.
  2. Потом мы создаем и экспортируем класс для каждого из ваших действий. Все они должны реализовать интерфейс Action из ngrx. Наконец, мы устанавливаем тип в одно из значений перечислений, и если вам нужно полезное содержимое для действия, вы добавляете его в конструктор класса.
  3. Наконец, мы экспортируем тип, содержащий наши классы действий. Это обеспечит нам проверку типов, которую мы можем использовать, например, в наших редукторах.

Создание Редукторов

  1. Объявление редуктора получает состояние и, в этом случае, действия пользователя и возвращает IUserState.
  2. Используя оператор switch, мы генерируем наблюдения для каждого возможного типа действия.
  3. Каждый случай возвращает новый объект, который является результатом слияния старого состояния и нового значения.
  4. Все редукторы имеют результат по умолчанию, который просто возвращает состояние без каких-либо изменений.

Добавим Эффекты

  1. Мы объявляем наши пользовательские эффекты с помощью инъекционного декоратора.
  2. Мы объявляем наши эффекты, используя декоратор эффектов, предоставленный ngrx/Effects.
  3. Используя действия, предоставленные ngrx / Effects, мы собираемся запустить конвейер нашего оператора для этого эффекта.
  4. Следующим шагом является установка типа действия эффекта с помощью оператора ofType.
  5. Следующие части представляют собой операторы rxjs, которые мы используем для получения того, что нам нужно (у нас уже есть ссылка на документацию по rxjs в этой статье).
  6. Наконец, в последнем операторе Effect отправит еще одно действие.
  7. В конструкторе мы внедряем сервисы, которые мы собираемся использовать, действия для ngrx / Effects, и в этом случае также хранилище (учтите, что это демо, и мы получаем выбранного пользователя из списка пользователей в наше хранилище).

Итоговая настройка

  1. Мы импортируем наши редукторы и предоставляем их в forRoot модуля хранилища.
  2. Мы импортируем наши эффекты и предоставляем их внутри массива в модуль forRoot эффектов.
  3. Мы устанавливаем конфигурацию для модуля состояния маршрутизатора, предоставляющего маршрутизатор stateKey.
  4. И мы добавляем инструменты разработчика магазина, если среда не является производственной.

Использование хранилища в некоторых компонентах

Во-первых, давайте получим конфигурацию при запуске приложения:

  1. Мы добавляем хранилище в наш app.component.
  2. Мы устанавливаем для свойства компонента значение селектора в конфигурации, потому что хотим отобразить часть этой информации в HTML.
  3. В onInit мы отправляем действие, чтобы получить конфигурацию.
  1. Подобно тому, как мы управляем конфигурацией, мы собираемся получить список пользователей. Сначала мы внедряем хранилище в компонент пользователя.
  2. На onInit мы отправляем действие, чтобы получить пользователей.
  3. Мы создаем свойство для компонента и присваиваем ему список пользователей, используя селектор списка пользователей.

Давайте посмотрим на компонент пользовательского контейнера:

Дочерние маршруты

Последнее обновление: 17.05.2021

В прошлых темах рассматривалась работа с обычными маршрутами. То есть система маршрутизации выбирает один из компонентов на основе url и
помещает его в главный компонент AppComponent. Но что если выбранный компонент сам должен принимать в качестве внутреннего содержимого какой-то другой компонент в зависимости от
запроса. В этому случае нам надо использовать дочерние маршруты (child route).

К примеру, возьмем проект из прошлых тем:

Добавим в папку src/app два простеньких компонента. Вначале добавим файл item.details.component.ts:

import { Component} from '@angular/core';
 
@Component({
    selector: 'item-details',
    template: `<h3>Информация о товаре</h3>`
})
export class ItemDetailsComponent{}

И также добавим второй файл item.stat.component.ts:

import { Component} from '@angular/core';
 
@Component({
    selector: 'item-stat',
    template: `<h3>Статистика товара</h3>`
})
export class ItemStatComponent{}

Итак, есть два компонента ItemDetailsComponent и ItemStatComponent, которые условно раскрывают различные стороны одно и того же товара. Логически они относятся к
ItemComponent, который также связан с определенным товаром.

Мы бы могли определить прямые маршруты к этим компонентам типа:

{ path: 'item/:id/details', component: ItemDetailsComponent},
{ path: 'item/:id/stat', component: ItemStatComponent},

Где в данном случае id — также параметр маршрута, представляющий условный id товара.

Но такие маршруты будут миновать компонент ItemComponent и никак его не затрагивают. Поэтому нам надо использовать другую организацию маршрутов. Для
этого изменим модуль AppModule следующим образом:

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import {Routes, RouterModule} from '@angular/router';
import { AppComponent }   from './app.component';
import { HomeComponent }   from './home.component';

import { ItemComponent }   from './item.component';
import { ItemStatComponent }   from './item.stat.component';
import { ItemDetailsComponent }   from './item.details.component';

// определение дочерних маршрутов
const itemRoutes: Routes = ;

const appRoutes: Routes =[

	{ path: 'item/:id', component: ItemComponent},
	{ path: 'item/:id', component: ItemComponent, children: itemRoutes},
	{ path: '', component: HomeComponent}
];

@NgModule({
    imports:      ,
    declarations: ,
    bootstrap:    
})
export class AppModule { }

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

{ path: 'item/:id', component: ItemComponent, children: itemRoutes},

Теперь изменим ItemComponent:

import { Component} from '@angular/core';
import { ActivatedRoute} from '@angular/router';
import {Subscription} from 'rxjs';
 
@Component({
    selector: 'item-info',
    template: `<h2>Товар `id`</h2>
			   <router-outlet></router-outlet>`
})
export class ItemComponent{ 
	
	id: any;
	private routeSubscription: Subscription;
	
	constructor(private route: ActivatedRoute){
		
		this.routeSubscription = route.params.subscribe(params=>this.id=params);
	}
}

Для вставки компонентов ItemDetailsComponent и ItemStatComponent здесь определен элемент .

И изменим главный компонент AppComponent, добавив в него для тестирования ссылки на ItemDetailsComponent и ItemStatComponent:

import { Component} from '@angular/core';
 
@Component({
    selector: 'my-app',
    template: `<div>
					<nav>
						<a routerLink="">Главная</a> |
						<a routerLink="/item/5/details">Информация о товаре</a> |
						<a routerLink="/item/5/stat">Статистика товара</a>
					</nav>
					<router-outlet></router-outlet>
			   </div>`
})
export class AppComponent {}

При переходе по подобным ссылкам будет срабатывать маршрутизация к компоненту ItemComponent и ему будет передаваться параметр маршрута — id. И также
будет срабатывать маршрутизация к ItemDetailsComponent или ItemStatComponent, если после id идет какой-нибудь сегмент «details» или «stat»:

НазадВперед

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector