10 полезных функций angular, которые вы упускали

Google ненавидит SPA

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

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

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

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

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

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

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

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

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

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

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

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

Как выглядит Angular-приложение?

Теперь, когда вы имеете некоторое представление об Angular, давайте углубимся в код. Начнём с небольшого приложения “hello world”. Все приложения Angular начинаются с НТМL-страницы, которая выглядит следующим образом.

В реальном приложении тег < script > внутри тега < head > может быть немного сложным, но в высокоуровневых приложениях он такой же, как и другие веб-приложениях – вы загружаете кусок JavaScript-кода в HTML-документ, и приложение работает.  

Есть одна уникальная вещь в выше приведённом примере – элемент < my-app >. Вы не используете этот элемент регулярно в веб-приложении. Цель Angular – постоянно расширять словарь НТМL, позволяя вам определять собственные теги.

Такие пользовательские теги называют компонентами, и вы можете определять их поведение в коде. Вот простейшая реализация элемента < my-app >:

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

TypeScript – надстройка над JavaScript, то есть весь синтаксис JavaScript доступен на TypeScript. Кстати, весь приведённый выше синтаксис – import, export, @Component и остальные – это или нынешние фичи JavaScript, или те, что появятся в ближайшем будущем. Так что, когда вы учите TypeScript, вы изучаете будущее JavaScript. TypeScript, к тому же, отличается превосходной документацией, к которой вы можете обратиться в любое время.

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

Давайте еще раз посмотрим на TypeScript-код, определяющий компонент < my-app >:

В Angular вы используете тег @Component, который известен как декоратор, чтобы отметить классы, которые учитывают элементы, которые могут быть использованы в вашей HTML-разметке. У вас есть возможность передавать свойства @Component для описания элемента. 

  • Свойство selector определяет имя тега при вводе в HTML. Использование селектора < my-app > показывает Angular, что делать, когда он видит тег < my-app > в HTML.
  • Свойство template контролирует, что HTML должен делать, когда используется компонент. Пример использования template: «< h1 >Hello World< /h1 >», тут видно, как Angular определяет, какие действия применять при < my-app > и почему это приложение представляет базовый тег < h1 > при предварительном просмотре в браузере. 

Отображение базового примера “Hello World” в браузере.

Действия (actions), редукторы (reducer), селекторы (select), хранилище (store) и побочные эффекты (effects) NGRX

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

На этой картинке мы видим жизненный цикл ngrx. Давайте разберём его …

1. В наиболее распространенном сценарии все начинается в представлении компонента (). Взаимодействие с пользователем может привести к тому, что компонент отправит действие ().

2.1. Если действие не вызывает эффект (), то редуктор отфильтрует действие (обычно с помощью оператора switch), и вернёт новое состояние, которое будет результатом слияния старого состояния со значением, которое изменилось после вызова действия.

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

2.2.1. После того, как эффект отработал (побочные эффекты закончились), он запускает новое действие «состояние-результат» (побочные эффекты могут быть успешными или неудачными), и мы возвращаемся к пункту 2.1.

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

Форма заказа

В этом примере мы рассмотрим код формы заказы, в которой автоматически выводится общая сумма. Здесь использована еще одна полезная функция AngularJS — фильтры. Фильтры позволяют вносить изменения в модели, а также объединять их с помощью символа «|». В приведенном ниже примере, используется фильтр валюты, чтобы перевести числовое значение в корректный формат цены — с разделением долларов и центов. Когда вы рассмотрите пример № 4, вы сможете с легкостью задавать свои собственные фильтры.

HTML:


Services

  • `service`.`name` {{service.price | currency}}

Total: {{total() | currency}}

JS:

function OrderFormController($scope){

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

	$scope.services = ;

	$scope.toggleActive = function(s){
		s.active = !s.active;
	};

	// Вспомогательный метод подсчета общей суммы по всем выбранным
	// позициям.

	$scope.total = function(){

		var total = 0;

		// Use the angular forEach helper method to
		// loop through the services array:

		angular.forEach($scope.services, function(s){
			if (s.active){
				total+= s.price;
			}
		});

		return total;
	};
}

CSS:

*{
	margin:0;
	padding:0;
}

body{
	font:15px/1.3 'Open Sans', sans-serif;
	color: #5e5b64;
	text-align:center;
}

a, a:visited {
	outline:none;
	color:#389dc1;
}

a:hover{
	text-decoration:none;
}

section, footer, header, aside, nav{
	display: block;
}

/*-------------------------
	Форма заказа
--------------------------*/

form{
	background-color: #61a1bc;
	border-radius: 2px;
	box-shadow: 0 1px 1px #ccc;
	width: 400px;
	padding: 35px 60px;
	margin: 50px auto;
}

form h1{
	color:#fff;
	font-size:64px;
	font-family:'Cookie', cursive;
	font-weight: normal;
	line-height:1;
	text-shadow:0 3px 0 rgba(0,0,0,0.1);
}

form ul{
	list-style:none;
	color:#fff;
	font-size:20px;
	font-weight:bold;
	text-align: left;
	margin:20px 0 15px;
}

form ul li{
	padding:20px 30px;
	background-color:#e35885;
	margin-bottom:8px;
	box-shadow:0 1px 1px rgba(0,0,0,0.1);
	cursor:pointer;
}

form ul li span{
	float:right;
}

form ul li.active{
	background-color:#8ec16d;
}

div.total{
	border-top:1px solid rgba(255,255,255,0.5);
	padding:15px 30px;
	font-size:20px;
	font-weight:bold;
	text-align: left;
	color:#fff;
}

div.total span{
	float:right;
}

Связка ng-repeat (описание) – это еще один полезный элемент Angular. Она позволяет запустить цикл обработки массива элементов, а также задать разметку для каждого из них. Она автоматически обновляет код, если один из элементов был изменен или удален.

Популярные встроенные Angular-директивы [ править | править код ]

С помощью директив AngularJS можно создавать пользовательские HTML-теги и атрибуты, чтобы добавить поведение некоторым элементам.

ng-app Объявляет элемент корневым для приложения. ng-bind Автоматически заменяет текст HTML-элемента на значение переданного выражения. ng-model То же, что и ng-bind, только обеспечивает двустороннее связывание данных. Изменится содержимое элемента — ангуляр изменит и значение модели. Изменится значение модели — ангуляр изменит текст внутри элемента. ng-class Определяет классы для динамической загрузки. ng-controller Определяет JavaScript-контроллер для вычисления HTML-выражений в соответствии с MVC. ng-repeat Создает экземпляр DOM для каждого элемента из коллекции. ng-show и ng-hide Показывает или скрывает элемент, в зависимости от значения логического выражения. ng-switch Создаёт экземпляр шаблона из множества вариантов, в зависимости от значения выражения. ng-view Базовая директива, отвечает за обработку маршрутов , которые принимают JSON перед отображением шаблонов, управляемых указанными контроллерами. ng-if Удаляет или создаёт часть DOM-дерева в зависимости от значения выражения. Если значение выражения, назначенного ngIf, равно false, элемент удаляется из DOM, иначе — вновь клонированный элемент вставляется в DOM.

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

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

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

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

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

Что такое AngularJS

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

AngularJS представляет собой opensource JavaScript-фреймворк, использующий шаблон MVC. Собственно использование MVC является его одной из отличительных особенностей.

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

Другой отличительной чертой фреймворка является двустороннее связывание, позволяющее динамически изменять данные в одном месте интерфейса при
изменении данных модели в другом. Таким образом, AngularJS синхронизирует модель и представление.

Кроме того, AngularJS поддерживает такие функциональности, как Ajax, управление структорой DOM, анимация, шаблоны, маршрутизация и так далее. Мощь фреймворка,
наличие богатого функционала во многом повлияла на то, что он находит свое применение во все большем количестве веб-приложений, являясь на данный
момент наверное одним из самых популярных javascript-фреймворков.

На момент написания данного руководства последней версией фреймворка была версия 1.6.4.

Начало работы c AngularJS

При загрузке zip-пакета мы найдем в нем кроме самой библиотеки (angular.js) еще ряд дополнительных файлов и их минимизированные версии:

  • angular-touch.js: предоставляет поддержку событий сенсорного экрана

  • angular-animate.js: предоставляет функциональность анимации

  • angular-aria.js: предоставляет поддержку aria-атрибутов (accesible rich internet application)

  • angular-mocks.js: предоставляет mock-объекты для юнит-тестирования

  • angular-route.js: обеспечивает механизм маршрутизации

  • angular-sanitize.js: предоставляет функционал для управления потенциально опасным контентом (javascript, html)

  • angular-cookies.js: обеспечивает функционал для управления куками

  • angular-loader.js: используется для загрузки angularjs-скриптов

  • angular-messages.js: предоставляет функционал для вывода сообщений

  • angular-resource.js: обеспечивает функциональность для работы с ресурсами

  • Папка i18n: содержит js-файлы для разных локалей

Из всех загруженных скриптов в архиве нас будет интересовать прежде всего файл angular.min.js

Теперь собственно создадим приложение. Оно будет стандартным HelloWorld. Код html-страницы будет следующим:

<!doctype html>
<html ng-app>
<head>
<meta charset="utf-8">
</head>
<body>
<label>Введите имя:</label>
<input type="text" ng-model="name" placeholder="Введите имя">

<h1>Добро пожаловать `name`!</h1>
     
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
</body>
</html>

Первое, наверное, что бросается в глаза — это новые атрибуты, добавленные к стандартным тегам html (в данном случае и
). Эти атрибуты являются директивами фреймворка AngularJS. Благодаря их встраиванию фреймворк позволяет добавить элементам определенное поведение.

Конкретно в данном случае директива объявляет элемент корневым для всего приложения, а
директива указывает модель «name», к которой будет привязано значение элемента input. И при изменении текста в элементе input, модель «name»
также будет динамически изменять свое значение.

Чуть ниже в элементе выводится значение этой модели.

И мы можем просто открыть данный файл в браузере и протестировать его работу.

Вперед

Что такое SPA, single-page application

Single-page application рас­шиф­ро­вы­ва­ет­ся как «при­ло­же­ние на одной стра­ни­це». Рабо­та­ет так: 

  1. Поль­зо­ва­тель пере­хо­дит на сайт. 
  2. Бра­у­зер отправ­ля­ет сер­вер­ный запрос. 
  3. Сер­вер воз­вра­ща­ет стра­ни­цу по запра­ши­ва­е­мо­му URL-адресу. 
  4. Пока поль­зо­ва­тель нахо­дит­ся на пер­вой стра­ни­це, сер­вер упа­ко­вы­ва­ет и пере­да­ёт все осталь­ные стра­ни­цы в фоно­вом режиме. 
  5. Когда поль­зо­ва­те­лю нуж­но перей­ти на дру­гую стра­ни­цу, у него «в фоне» уже загру­же­но всё необходимое.

Single-page озна­ча­ет, что сайт тех­ни­че­ски рабо­та­ет как бы на одной стра­ни­це: там есть шап­ка, под­вал, какое-то меню, а основ­ное «мясо» стра­ни­цы загру­жа­ет­ся дина­ми­че­ски, в фоно­вом режи­ме, без уча­стия поль­зо­ва­те­ля. Самый нагляд­ный при­мер тако­го при­ло­же­ния — это соц­сеть VK: пока вы листа­е­те лен­ту, вам могут напи­сать сооб­ще­ние, и оно появит­ся на экране само, без необ­хо­ди­мо­сти пере­за­гру­жать страницу.

Без SPA вам при­хо­ди­лось бы посто­ян­но пере­за­гру­жать стра­ни­цу с сооб­ще­ни­я­ми, что­бы понять, напи­са­ли вам или нет. А с SPA всё про­ис­хо­дит само.

Логика внутри конструктора сервиса

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

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

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

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

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

Может быть, сейчас вы думаете:

Да, я могу! Пожалуйста, не теряйте интерес, мы приближаемся к концу! Давайте посмотрим, как использовать наше хранилище …

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

Файл с описание компонента приложения

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

Вот и всё … Мы уже написали код эффекта, который будет обрабатывать это действие, и редуктор, который будет обрабатывать успех этого эффекта. Как только хранилище приобретёт новое состояние, селектор изменит значение нашего свойства. Удивительно!

Вот как мы связываем данные конифгурации в HTML:

Файл с описанием HTML разметки компонента навигации приложения

Как только у изменится значение, мы увидим его в HTML.

Теперь давайте посмотрим список пользователей

Файл с описанием компонента пользователя

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

HTML выглядит так:

Файл с описанием HTML разметки компонента пользователя

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

Отлично… а как мы показываем выбранного пользователя?…

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

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

Этот компонент получает параметр из (текущего url), а с остальным вы, вероятно, уже знакомы. Отправление в качестве параметра, выбор выбранного пользователя…

Если вы хотите увидеть весь код, просто зайдите в репозиторий GitHub.

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

Объект Observable и библиотека RxJS

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

Методы класса HttpClient после выполнения запроса возвращают объект Observable<any>,
который определен в библиотеке RxJS («Reactive Extensions»). Она не является непосредственно
частью Angular, однако широко используется особенно при взаимодействии с сервером по http. Эта библиотека реализует паттерн «асинхронный наблюдатель»
(asynchronous observable). Так, выполнение запроса к серверу с помощью класса HttpClient выполняются в асинхронном режиме.

Естественно чтобы задействовать функционал RxJS в приложении, в проект должна быть добавлена соответствующая зависимость «rxjs»:

{
    "name": "helloapp",
    "version": "1.0.0",
    "description": "First Angular 11 Project",
    "author": "Eugene Popov <metanit.com>",
    "scripts": {
        "ng": "ng",
		"start": "ng serve",
		"build": "ng build"
    },
    "dependencies": {
        "rxjs": "~6.6.3",
		// остальное содержимое секции
    },
    "devDependencies": {
        // содержимое секции
    }
}

Используя специальные методы для объекта Observable, например, map и filter, можно произвести некоторую постобработку
полученных от сервера результатов.

Например, определим в файле users.json данные, которые напрямую не соответствуют массиву объектов User:

{ 
	"userList":
	
}

В качестве модели данных используем класс User:

export class User{
	name: string;
	age: number;
}

То есть в данном случае у нас нет соответствия по именам свойствам: name — username и age — userage.

Определим следующий код сервиса, который будет получать данные из users.json:

import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {User} from './user';
import {Observable} from 'rxjs';
import { map } from 'rxjs/operators';
  
@Injectable()
export class HttpService{
  
    constructor(private http: HttpClient){ }
      
    getUsers() : Observable<User[]> {
        return this.http.get('assets/users.json').pipe(map(data=>{
            let usersList = data;
            return usersList.map(function(user:any) {
                return {name: user.userName, age: user.userAge};
              });
        }));
    }
}

Смысл использования специального сервиса для работы с http заключается в сокрытии деталей отправки запросов.
Компонент же ожидает получить какие-то конкретные данные, например, в виде набора объектов User. С помощью метода map библиотеки rxjs можно
преобразовать данные из одного формата в другой.

У результата метода мы можем вызвать метод pipe(), который позволяет обработать результаты запроса. Для этого
метод pipe в качестве первого параметра принимает функцию обработки данных запроса. В данном случае в роли такой функции выступает оператор map,
который преобразует результаты запроса в новые объекты.

Но чтобы использовать элементы библиотеки RxJS, их надо импортировать:

import {Observable} from 'rxjs';
import { map } from 'rxjs/operators';

В итоге весь метод возвращает объект .

Теперь используем сервис в классе компонента:

import { Component, OnInit} from '@angular/core';
import { HttpService} from './http.service';
import {User} from './user';
  
@Component({
    selector: 'my-app',
    template: `<ul>
                <li *ngFor="let user of users">
                <p>Имя пользователя: {{user?.name}}</p>
                <p>Возраст пользователя: {{user?.age}}</p>
                </li>
            </ul>`,
    providers: 
})
export class AppComponent implements OnInit { 
  
    users: User[]=[];
    
    constructor(private httpService: HttpService){}
     
    ngOnInit(){
         
        this.httpService.getUsers().subscribe(data => this.users=data);
    }
}

НазадВперед

Создание редукторов (reducers)

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

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

Файл с описанием редукторов пользователя

Давайте обсудим реализацию:

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

И это всё. В редукторе больше ничего нет. Давайте посмотрим на редукторы конфигурации :

Файл с описанием редукторов конфигурации

Глядя на этот код, вы, вероятно, легко его понимаете, т. к. мы уже это всё обсуждали.

Наконец, давайте посмотрим на редукторы приложения :

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

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

Отлично!… Теперь у нас есть наше состояние, наши действия, наши редукторы, но нам всё ещё нужны эффекты и селекторы. Давайте добавим наши эффекты …

AngularJS Extends HTML

AngularJS extends HTML with ng-directives.

The ng-app directive defines an AngularJS application.

The ng-model directive binds the value of HTML controls
(input, select, textarea) to application data.

The ng-bind directive binds application data to the HTML
view.

AngularJS Example

<!DOCTYPE html>
<html><script
src=»https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js»></script>
<body><div ng-app=»»>
  <p>Name: <input type=»text» ng-model=»name»></p>
  <p ng-bind=»name»></p>
</div>
</body>
</html>

Example explained:

AngularJS starts automatically when the web page has loaded.

The ng-app directive tells AngularJS that the <div> element is the «owner» of an
AngularJS application.

The ng-model directive binds the value of the input field to
the application variable name.

The ng-bind directive binds the content of the <p> element to the application variable name.

Установка библиотеки

Мы собираемся использовать для создания проекта, а затем добавить библиотеки .

Давайте создадим проект:

ng new angular-ngrx —style=scss

Давайте добавим библиотеки , которые мы будем использовать:

npm install @ngrx/core @ngrx/store @ngrx/effects @ngrx/store-devtools @ngrx/router-store --save

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

  • — мощная утилита для отладки.
  • — сохраняет состояние маршрутизатора 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. Мы создаем свойство для компонента и присваиваем ему список пользователей, используя селектор списка пользователей.

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

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

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

Adblock
detector