Новый Angular на русском. Чек-лист для начала разработки

Новый Angular на русском. Чек-лист для начала разработки

Angular – это JavaScript-фреймворк для разработки мобильных и веб-приложений. Он начался как Платформа JavaScript на стороне клиента для написания лучших интерфейсных приложений, которые работают в веб-браузере. Сегодня Angular использует достижения современной веб-разработки для создания SPA (single page applicatiion – одностраничных приложений), кросс-платформенных и нативных мобильных приложений. Angular приложения могут быть написаны с помощью ES5 или ES6 вместе с TypeScript. TypeScript представляет собой самый популярный выбор для Angular приложений в open-source. TypeScript имеет мощную типизацию и среди многих других функций, обеспечивает автодополнение, навигацию и рефакторинг, что очень полезно в больших проектах. Поскольку Typescript повсюду использует ЕS6, в один прекрасный момент вы поймаете себя на мысли, будто ваш ES6 на стероидах

Новый Angular на русском. Чек-лист для начала разработки
Компоненты
Компоненты являются строительными блоками angular приложения. Компонент представляет собой комбинацию шаблона HTML и класса написанного на TypeScript (или JavaScript). Для создания компонента в Angular с Тайпскриптом, необходимо создать класс в файле с расширением .ts и украсить его с компонентом декоратор. Рассмотрим пример ниже:

import { Component } from '@angular/core';
@Component({
selector: 'hello-ng-world',
template: `<h1>Hello Angular world</h1>`
})
export class HelloWorld {
}

Component, импортирован из корневой структуры Angular. Декоратор компонента позволяет задать метаданные для данного компонента. Из них выделю часто используемые метаданные: селектор: имя, данное для идентификации компонента. В примере, который мы только что видели, hello-ng-world используется для ссылки на компонент в другом шаблоне или HTML-коде. Например, тег <hello-ng-world></hello-ng-world> загрузит на страницу данный компонент шаблон: делается разметка для данного компонента. При использовании компонента применяются привязки с переменными в классе компонента, логика стиля и представления. templateUrl: url-адрес внешнего файла, содержащего шаблон для представления. Для лучшей организации кода шаблон можно переместить в отдельный файл, а путь можно указать в качестве значения templateUrl. стили: используется для конкретных стилей данного компонента. Они относятся к компоненту. styleUrls: определение CSS-файлы, содержащие стиль для компонента. Мы можем указать один или несколько файлов CSS в массиве. Из этих файлов CSS, классы и другие стили могут быть применены в шаблоне компонента.
Привязка данных
Интерполяция строк – это простой способ отображения данных в приложении Angular. Рассмотрим следующий синтаксис в шаблоне Angular, чтобы показать значение переменной.
<h1>Hello {{title}} world</h1>

title-имя переменной. Обратите внимание на одинарные кавычки (backtick`) вокруг строки, которая является синтаксисом ES6/ES2015 для смешивания переменных в строке. Полный фрагмент кода для компонента выглядит следующим образом:

import { Component } from '@angular/core';
@Component({
selector: 'hello-ng-world',
template: `<h1>Hello {{title}} world</h1>`
})
export class HelloWorld {
title = 'Angular 4';
}

Для отображения значения в текстовом поле используйте свойство DOM “value”, заключенное в квадратные скобки. Поскольку он использует атрибут DOM, новички смогут с легкостью понять и быстро начать пользоваться данной директивой. “title” – имя переменной в компоненте.

<input type="text" [value]="title">

Такая привязка может быть применена к любому атрибуту HTML. Рассмотрим следующий пример, где Заголовок используется в качестве плейсхолдера в input поле.

<input type="text" [placeholder]="title" >

События
Чтобы связать событие DOM с функцией в компоненте, используйте следующий синтаксис. Оберните событие DOM в круглую скобку, которая вызывает функцию в компоненте.

<button (click)="updateTime()">Update Time</button>

Прием пользовательского ввода
По мере того, как пользователь вводит значения в текстовых полях или выделяет их в раскрывающемся списке или на радио-кнопке, значения должны обновляться в переменных компонента/класса. Для этого мы можем использовать события. Следующий фрагмент кода обновляет значение в текстовом поле до переменной компонента. Html файл:

<input type="text" (change)="updateValue($event)">
ts файл:
updateValue(event: Event){
// event.target.value – это значение текстового поля
// Его вставляем в label.
this.label = event.target.value;
}

Примечание: учитывая, что это базовый пример, параметр события для функции выше имеет Тип any. Для лучшей проверки типа, желательно, чтобы объявить его в KeyboardEvent типа.
Чуть интереснее 
В предыдущем примере, $event – это передаваемое событие, которое несет в себе много информации. Он инкапсулирует полный цикл событий из dom, которые срабатывают. Однако все что нам нужно сейчас – это значение текстового поля. Рассмотрим следующий фрагмент кода, который является доработанной реализацией той же ситуации. Используйте переменную ссылки на шаблон в текстовом поле.

<input type="text" #label1 (change)="updateValue(label1.value)">

Обратите внимание на функцию updateValue при изменении, которая принимает поле value на label1 (ссылочной переменной шаблона). Функция update теперь может задать значение переменной класса.

updateValue(value: any){
// It is set to the label.
this.label = value;
}

Банан в коробке
Из Angular 2 и далее двусторонняя привязка данных не является безусловной. Рассмотрим следующий пример. Поскольку пользователь изменяет значение в текстовом поле, он не мгновенно обновляет Заголовок в h1.

<h1> {{title}} </h1>
<input type="text" [value]="title">

Используйте следующий синтаксис для двусторонней привязки данных. Он сочетает привязку значения и привязку события с короткой формой – [()]. На разговорном языке это называется banana in box, как банан в коробке.

<h1> {{title}} </h1>
<input type="text" [(ngModel)]="title" name="title">

ngModel и формы ngModel полезен не только для двусторонней привязки данных, но и для некоторых дополнительных классов CSS, указывающих состояние поля формы. Рассмотрим следующие поля формы-имя и фамилия. ngModel установлен в #fname и #lname поля на модели представления (переменная vm, определенная в компоненте).

<input type="text" [(ngModel)]="vm.fname" name="firstName" #fname required /> {{fname.className}} <br />
<input type="text" [(ngModel)]="vm.lname" name="lastName" #lname /> {{lname.className}}

Пожалуйста, обратите внимание, если ngModel используется в форме, необходимо добавить атрибут name. Элемент управления регистрируется в форме (родительский элемент использует значение атрибута name). Не предоставляя имя атрибута приведет к следующей ошибке. «Если ngModel используется внутри тега Form, либо атрибута name должно быть задано или контроля форма должна быть определена как “автономные” в ngModelOptions.» Angular добавляет к input’ам следующие классы CSS, как и когда пользователь начинает использовать элементы ввода формы. ng-untouched – класс CSS будет установлен в поле формы при загрузке страницы. Пользователь еще не использовал поле и не установил на него фокус клавиатуры. ng-touched – класс CSS будет добавлен в поле формы, когда пользователь устанавливает фокус, перемещая курсор клавиатуры или щелкает по нему. Этот класс устанавливается в момент выхода из формы. ng-pristine – этот класс имеет значение пока значение на поле не изменилось. ng-dirty – этот класс задается когда пользователь изменяет значение. ng-valid – это класс, когда все поля формы проверки не устраивает, никто не в состоянии. Например, обязательное поле имеет значение. ng-invalid – этот класс устанавливается, когда форма проверки полей не удается. Например, обязательное поле с пустым значением. Эта функция позволяет настроить класс CSS на основе сценария. Например, недопустимое поле ввода может иметь красный фон, выделяющий его для пользователя. Определите следующий CSS для данного компонента с элементами формы.

.ng-invalid{
background: orange;
}

Рисунок 1. Он изображает два поля формы с классами CSS, указывая состояние поля формы рядом с ним.
ngModule
Создайте angular модуль с помощью функции декоратора ngModule для класса. Модуль помогает пакету угловые артефакты как компоненты, директивы, пайпы (pipes, класс, с помощью которого можно манипулировать данными при ngFor цикле, например фильтровать – примечание автора) etc. Это помогает с предварительной компиляции (AoT). Модуль подвергает действию компоненты, директивы и пайпы к другим Angular модулям. Это также позволяет определить зависимость от других Angular модулей. Рассмотрим следующий пример кода. Примечание: все компоненты должны быть объявлены с Angular модулем.

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { MyAppComponent } from './app.component';

@NgModule({
imports: [ BrowserModule ],
declarations: [ MyAppComponent ],
bootstrap: [ MyAppComponent ]
})
export class MyAppModule { }

Импортируйте ngModule из Angular core. Это функция декоратора, которая может быть применена к классу. Ниже приведены метаданные, которые мы предоставляем для создания модуля. imports: зависимость от BrowserModule указывается с импортом. Заметьте, это массив. Зависимость нескольких модулей может быть указана при импорте. declarations: все компоненты, связанные с текущим модулем, могут быть указаны в качестве значений в declarationsarray. bootstrap: у angular приложения есть корневой модуль, который будет иметь корневой компонент, отображаемый на HTML. Для текущего модуля первым загружаемым компонентом является MyAppComponent (импортированный из относительного пути).
Сервисы
Создавайте сервис компонент в angular приложения для любой части повторного использования кода! Это может быть доступ к API службы на стороне сервера, предоставление информации о конфигурации и т. д. Чтобы создать службу, импортируйте и добавьте css классы с
(Typescript) модуль @angular/core.

Это позволяет angular создать экземпляр и внедрить данную службу в компонент или другую службу. Рассмотрим следующий гипотетический пример. Он создает TimeService для предоставления значений даты и времени в согласованном формате в приложении. Функция getTime () может вызываться в компоненте приложения.

import { Injectable } from '@angular/core';

@Injectable()
export class TimeService {

constructor() { }

getTime(){
return `${new Date().getHours()} : ${new Date().getMinutes()} : ${new Date().getSeconds()}`;
}

}

Инъекционные зависимости (DI)
В разделе обслуживания мы видели создание службы, украшая ее Injectable() (Инъекционной т.е.) функцией. Это помогает Angular инжектору создать объект сервиса. Это необходимо только в том случае, если служба имеет другие добавленные зависимости. Тем не менее, это хорошая практика, чтобы добавить Injectable() декоратор для всех служб (даже тех, которые не имеют зависимостей), чтобы поддерживать согласованность кода. С помощью инъекционных зависимостей Angular создается экземпляр службы, которая разгружает создание объектов, позволяет легко реализовать одноэлементный код и делает код более удобным для модульного тестирования.
Снабжение компонентов сервисами (Provide a service)
Чтобы внедрить службу в компонент, укажите службу в списке провайдеров. Это может быть сделано на уровне модуля (чтобы быть доступным в значительной степени) или на уровне компонента (чтобы ограничить область). На этом этапе сервис создается с помощью Angular. Вот пример компонента, в котором внедренный экземпляр службы доступен компоненту и всем его дочерним компонентам.

import { Component } from '@angular/core';
import { TimeService } from './time.service';
@Component({
selector: 'app-root',
providers: [TimeService],
template: `<div>Date: {{timeValue}}</div>,
})
export class SampleComponent {
// Component definition
}

Чтобы завершить процесс DI, укажите сервис в качестве свойства параметра в конструкторе.
export class SampleComponent {
timeValue: string = this.time.getTime(); // Template shows

constructor(private time: TimeService){
}
}

Обратитесь к внедрению службы времени, ниже,
import { Injectable } from '@angular/core';

@Injectable()
export class TimeService {

constructor() { }

getTime(){
let dateObj: Date = new Date();
return `${dateObj.getDay()}/${dateObj.getMonth()}/${dateObj.getFullYear()}`;
}

}

Предоставление сервиса на уровне модуля.
Когда служба TimeService предоставляется на уровне модуля (вместо уровня компонента), экземпляр службы доступен для модуля (и приложения). Он работает как самостоятельная единица сквозь всё приложение.

@NgModule({
declarations: [
AppComponent,
SampleComponent
],
imports: [
BrowserModule
],
providers: [TimeService],
bootstrap: [AppComponent]
})
export class AppModule { }

Альтернативный синтаксис для провайдеров сервисов
В приведенном выше примере оператор провайдера является сокращенным вариантом, но есть вариант с указанием альтернативной реализацией класса,

// instead of providers: [TimeService] you may use the following,
providers: [{provide: TimeService, useClass: TimeService}]

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

providers: [{provide: TimeService, useClass: AlternateTimeService}]

Для примера AlternateTimeService предоставляет значение даты и времени. Сделан а копия TimeService, от который мы берем только значение даты.

@Injectable()
export class AlternateTimeService extends TimeService {

constructor() {
super();
}

getTime(){
let dateObj: Date = new Date();
return `${dateObj.getDay()}/${dateObj.getMonth()}/${dateObj.getFullYear()}
${dateObj.getHours()}:${dateObj.getMinutes()}`;
}
}

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

[{provide: TimeService, useClass: AlternateTimeService}]
providers: [AlternateTimeService, {provide: TimeService, useExisting: AlternateTimeService}]

Предоставление интерфейса и его реализация
Вариант предоставлять интерфейс и реализацию в качестве класса или значения может показаться хорошей идеей. Рассмотрим следующий интерфейс.
interface Time{
getTime(): string
}
export default Time;

Это может быть реализовано в TimeService.
@Injectable()
export class TimeService implements Time {
constructor() { }

getTime(){
let dateObj: Date = new Date();
return `${dateObj.getDay()}/${dateObj.getMonth()}/${dateObj.getFullYear()}`;
}
}

На данный момент мы не можем реализовать интерфейс времени и Класс TimeService, как в приведенном выше примере. Следующий фрагмент кода не работает, поскольку интерфейс TypeScript не компилируется в любой Эквивалент в JavaScript. providers:

[{provide: Time, useClass: TimeService}] // Wrong Чтобы сделать эту работу, импортируйте Inject (декоратор) и InjectionToken from @angular/core.. // create an object of InjectionToken that confines to interface Time let Time_Service = new InjectionToken('Time_Service');
// Provide the injector token with interface implementation. providers: [{provide: Time_Service, useClass: TimeService}]
// inject the token with @inject decorator
constructor(@Inject(Time_Service) ts,) {
this.timeService = ts;
}

// We can now use this.timeService.getTime().
Предоставление значения
Нам не всегда нужен класс, который будет предоставляться в качестве сервиса. Следующий синтаксис позволяет предоставлять объект JSON. Обратите внимание, что у объекта JSON есть функция getTime (), которая может использоваться в компонентах.
providers: [{provide: TimeService, useValue: {
getTime: () => `${dateObj.getDay()} – ${dateObj.getMonth()} – ${dateObj.getFullYear()}`
}}]

Примечание: для реализации, подобной разделу “6.5 Предоставление интерфейса и его реализация”, предоставьте useValue вместо useClass. Остальная часть реализации остается прежней.

providers: [provide: Time_Service, useValue: {
getTime: () => 'A date value'
}}]

Директивы
Из Angular 2/4 и в дальнейших версиях, директивы широко классифицируются как:
Components – включает в себя шаблон. Они основные строительные блоки angular применения. См. Раздел компонента в статье.
Structural directives – директива по управлению версткой. Он добавляется в качестве атрибута в элементе и контролирует поток в дом. Пример NgFor, NgIf и т. д.
Attribute directives – добавляет динамическое поведение и стиль к элементу в шаблоне. Пример NgStyle.

Ng-if… else
Эти директивы являются структурными, чтобы отображать шаблон согласно определенным условиям. Рассмотрим следующий пример. В ngIf директива закрывает от публикации строчку Time: [title], когда значение title задано (возвращает true, а не false). Условие else показывает шаблон, если для заголовка не задано значение. Обратите внимание на синтаксис здесь, директива с префиксом звездочки.

<div *ngIf="title; else noTitle">
Time: {{title}}
</div>
<ng-template #noTitle> Click on the button to see time. </ng-template>

Ng-Template
Является структурным директивой, которая не отображается по умолчанию. Это помогает группировать содержимое под элементом. По умолчанию шаблон отображается в виде комментария HTML. Содержание показано условно.

<div *ngIf="isTrue; then tmplWhenTrue else tmplWhenFalse"></div>
<ng-template #tmplWhenTrue >I show-up when isTrue is true. </ng-template>
<ng-template #tmplWhenFalse > I show-up when isTrue is false </ng-template>

Примечание: вместо ng-if…else (as in ng-if…else section), для лучшей читаемости кода, можно использовать, if…then…else. Здесь элемент, показанный при условии true, также перемещается в шаблоне.
Ng-Container
Ng-container – это еще одна директива / компонент для группировки HTML-элементов. Мы можем группировать элементы с помощью тега как div или span. Однако во многих приложениях могут применяться стили по умолчанию для этих элементов. Чтобы быть более предсказуемым, Ng-Container является предпочтительным. Он группирует элементы, но не отображает себя как HTML-тег. Рассмотрим следующий пример,

// Consider value of title is Angular
Welcome <div *ngIf="title">to <i>the</i> {{title}} world.</div>

Этот элемент рендериться как:
Результат в html: Он не отображался в одной строке из-за div. Мы можем изменить поведение с помощью CSS. Тем не менее, мы можем иметь стиль, который применяется для div по умолчанию. Это может привести к неожиданной стилизации строки в div. Вместо этого, рассмотрите возможность использования Ng-container
Welcome <ng-container *ngIf=”title”>to <i>the</i> {{title}} world.</ng-container>

HTML результат. ng-container не появился как элемент

NgSwitch и NgSwitchCase
Мы можем использовать оператор случая переключения в Angular шаблонах. Это похоже на switch..case в JavaScript. Рассмотрим следующий фрагмент. isMetric – это переменная компонента. Если его значение True, он будет показывать по Цельсию в качестве метки, иначе он будет показывать по Фаренгейту. Обратите внимание ngSwitch – это директива атрибут, а ngSwitchCase является структурным директивы.
<div [ngSwitch]=”isMetric”>
<div *ngSwitchCase=”true”>Degree Celsius</div>
<div *ngSwitchCase=”false”>Fahrenheit</div>
</div>

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

<div [ngSwitch]="isMetric">
<div *ngSwitchCase="true">Degree Celsius</div>
<div *ngSwitchDefault>Fahrenheit</div>
</div>

Input функциональный декоратор
Переменная класса может быть настроена в качестве входных данных для директивы. Значение будет предоставлено компонентом, использующим директиву. Рассмотрим следующий фрагмент кода. Это компонент, который показывает поля входа в систему. (Компонент-это тип директивы). Компонент вызова компонента входа может установить showRegister значение True, в результате чего показывать кнопку “Регистрация”. Чтобы сделать переменную класса входных данных, пометок с функцией ввода декоратор.
Import Input()
import { Component, OnInit, Input } from ‘@angular/core’;

Аннотация с функцией декоратора @Input() showRegister: boolean; Используйте входное значение в компоненте, который находится в шаблоне в данном примере.
<div>
<input type=”text” placeholder=”User Id” />
<input type=”password” placeholder=”Password” />
<span *ngIf=”showRegister”><button>Register</button></span>
<button>Go</button>
</div>

При использовании компонента укажите входные данные: Чтобы использовать привязку вместо того, чтобы обеспечить значение напрямую, используйте следующий синтаксис:
<app-login [shouldShowRegister]=”isRegisterVisible”></app-login>

Мы могли бы предоставить другое имя для атрибута, отличный от переменной. Рассмотрим следующий фрагмент:
@Input(“should-show-register”) showRegister: boolean;

Теперь, используйте атрибут should-show-register вместо переменной showRegister имя.
<app-login should-show-register=”true”></app-login>

Output функциональный декоратор
События, создаваемые директивой, выводятся в компонент (или директиву) с использованием данной директивы. В примере входа в систему при нажатии кнопки вход в систему событие может быть создано с идентификатором пользователя и паролем. Рассмотрим следующий фрагмент. Импортируйте декоратор Output и EventEmitter,
import { Component, OnInit, Input, Output, EventEmitter } from ‘@angular/core’;

Декларируйте Output события типа EventEmitter
@Output() onLogin: EventEmitter<{userId: string, password: string}>;

Обратите внимание на универсальный Тип (анонимный) EventEmitter для onLogin. Ожидается, что он выдаст объект с идентификатором пользователя и паролем. Затем инициализируйте объект.
constructor() {
this.onLogin = new EventEmitter();
}

Компонент запускает событие. В примере, когда пользователь нажимает на login, он выдает событие со следующей функцией. Вот шаблон:
<button (click)=”loginClicked(userId.value, password.value)”>Go</button>
..и обработчик событий:
loginClicked(userId, password){
this.onLogin.next({userId, password});
}

При использовании компонента укажите обработчик входа для выходного события onlogin.
<app-login (onLogin)=”loginHandler($event)”></app-login>

Обработчик входа получает идентификатор пользователя и пароль от компонента app-login
loginHandler(event){
console.log(event);
// Perform login action.
}

// Output: Object {userId: “sampleUser”, password: “samplePassword”}

Подобно входному декоратору, выходной декоратор может указать имя события для использования компонента / директивы. Это не обязательно имя переменной. Рассмотрим следующий фрагмент.
@Output(“login”) onLogin: EventEmitter<{userId: string, password: string}>;

..при использовании компонента:
<app-login (login)=”loginHandler($event)”></app-login>

Стратегия Обнаружения Изменений
Angular изменения распространяются сверху вниз, от родительских компонентов для дочерних компонентов. Каждый компонент в Angular имеет эквивалентный класс обнаружения изменений. При обновлении модели компонентов сравниваются предыдущие и новые значения. После изменения модели будут обновлены в DOM. Для входных данных компонентов, таких как number и string, переменные являются неизменяемыми. Как только изменяется величина, изменяется флаги класса и тогда DOM дерево обновляется. Для типов объектов, сравнение может быть одно из двух, Поверхностное сравнение: сравнение ссылок на объекты. Если одно или несколько полей в объекте обновлены, ссылка на объект не изменяется. Неглубокая проверка не заметит изменения. Однако этот подход лучше всего подходит для неизменяемых типов объектов. То есть, объекты не могут быть изменены. Изменения должны обрабатываться путем создания нового экземпляра объекта. Глубокое сравнение: перебор каждого поля объекта и сравнение с предыдущим значением. Это также определяет изменение изменяемого объекта. То есть, если одно из полей на объекте будет обновлено, то изменение будет замечено.
Стратегия отслеживания изменений для компонента
Для компонента мы можем добавить аннотацию одну из двух стратегий отслеживания ChangeDetectionStrategy.Default: Как понятно из имени, это стратегия по умолчанию, когда ничто явно не добавлено в виде аннотации на компоненте. С помощью этой стратегии, если компонент принимает Тип объекта в input поле, он выполняет глубокое сравнение при каждом изменении. То есть, если одно из полей изменилось, оно будет перебирать все поля и определять изменения и обновлять DOM. Рассмотрим следующий пример:

import { Component, OnInit, Input, ChangeDetectionStrategy } from '@angular/core';

@Component({
selector: 'app-child',
template: ' <h2>{{values.title}}</h2> <h2>{{values.description}}</h2>',
styleUrls: ['./child.component.css'],
changeDetection: ChangeDetectionStrategy.Default
})
export class ChildComponent implements OnInit {

// Input is an object type.
@Input() values: {
title: string;
description: string;
}

constructor() { }

ngOnInit() {}

}

Обратите внимание, стратегия обнаружения изменений упоминается как ChangeDetectionStrategy. По умолчанию, это значение в любом компоненте. Входными данными для компонента является Тип объекта с двумя полями title и description. Вот фрагмент кода шаблона родительского компонента.
<app-child [values]=”values”></app-child>

Обработчик событий в родительском компоненте описан ниже. Инициализация происходит, возможно, действием пользователя или другими событиями.
updateValues(param1, param2){
this.values.title = param1;
this.values.description = param2;
}

Обратите внимание, мы обновляем значение объекта. Ссылка на объект не меняется. Однако дочерний компонент обновляет DOM, поскольку стратегия выполняет глубокое сравнение.
ChangeDetectionStrategy.OnPush:
Стратегия по умолчанию эффективна для идентификации изменений. Тем не менее, она выполняется достаточно долго, поскольку функция должна пройти через весь объект, чтобы определить изменение. Для повышения производительности при обнаружении изменений рекомендуется использовать стратегию OnPush. Выполняет неглубокое сравнение входного объекта с предыдущим объектом. То есть он сравнивает только ссылку на объект. Фрагмент кода, который мы только что видели, не будет работать со стратегией OnPush. В примере ссылка не изменяется, поскольку мы изменяем значения на объекте. Дочерний компонент не будет обновлять DOM. Когда мы меняем стратегию на OnPush для компонента, входной объект должен быть неизменяемым. Мы должны создать новый экземпляр входного объекта, каждый раз, когда происходит изменение. Это изменяет ссылку на объект и, следовательно, сравнение определяет изменение. Рассмотрим следующий фрагмент кода для обработки события изменения в родительском элементе.
updateValues(param1, param2){
this.values = { // create a new object for each change.
title: param1,
description: param2
}
}

Примечание: несмотря на то, что вышеупомянутое решение для обработчика событий updateValues могло бы работать хорошо со стратегией OnPush, желательно использовать immutable.js для обеспечения неизменности с объектами или наблюдаемыми объектами с помощью RxJS или любой другой observable библиотеки.
Передача в Angular
В этих двух разделах (input и output декораторы), мы уже видели, как использовать атрибуты компонента для ввода и вывода. Как насчет доступа к содержимому внутри элемента, между тегами begin и end? AngularJS 1.х была передача в директивах, которые позволяли вставлять содержимое для передачи внутри элемента, чтобы это выглядело как часть директивы. Например, элемент <синий></синий> может содержать элементы, выражений и текст внутри элемента. Компонент будет применять синий цвет фона и показывать содержимое.
<blue>sample text</blue>

В шаблоне синего компонента используйте NG-content для доступа к содержимому внутри элемента. CSS класс blue применяется для стилизации.
<div class=”blue”>
<ng-content></ng-content>
</div>

ng-content shows sample text from above example. It may contain more elements, data binding expressions etc. NG-content показывает sample text из примера выше. Он может содержать больше элементов, привязку данных и т. д.
Использование observables в Angular шаблонах
Observable data по определению может быть недоступна при отрисовке шаблона. Директива *ngIf может использоваться для условного отображения раздела. Рассмотрим следующий пример.
<div *ngIf=”asyncData | async; else loading; let title”>
Title: {{title}}
</div>
<ng-template #loading> Loading… </ng-template>

Обратите внимание на асинхронный пайп async. В приведенном выше примере проверяется, что asyncData «чекается» на возврат данных. Когда observable не имеет данных, он отображает загрузку шаблона. Когда наблюдаемые данные возвращаются, значение устанавливается на заголовок переменной. Асинхронный пайп работает также и с промисами. NgFor Используйте * ngFor директиву по проходу по массиву или observable. Следующий код выполняет итерацию через массив цветов и каждый элемент в массиве называется новым цветом переменной.
<ul *ngFor=”let color of colors”>
<li>{{color}}</li>
</ul>
/* component declares array as colors= [“red”, “blue”, “green”, “yellow”, “violet”]; */

Примечание. Используйте асинхронный канал, если цвета являются наблюдаемыми или обещаниями.
Strict Null Check
В TypeScript 4 введен строгий контроль нуля для лучшей проверки типов. TypeScript ( JavaScript) имеет специальные типы, а именно null и undefined. При строгой проверке типа, разрешенной для приложения с Angular выражением, null или undefined не могут быть назначены переменной, если они не имеют такого типа. Рассмотрим следующий пример:
var firstName: string, lastName: string ;
//returns an error, Type ‘null’ is not assignable to type ‘string’.
firstName = null;
// returns an error, Type ‘undefined’ is not assignable to type ‘string’.
lastName = undefined;

Теперь явно укажите нулевые и неопределенные типы. Перепишите объявление переменной следующим образом:
var firstName: string | null, lastName: string | undefined ;
// This will work
firstName = null;
lastName = undefined;
По умолчанию strictNullCheck отключен. Чтобы включить strictNullCheck, отредактируйте tsconfig.json. Добавить “strictNullChecks”: true в compilerOptions

HTTP API вызовы и Observables
Используйте встроенную службу Http с модуля ‘@angular/http’ , чтобы вызвать вызовы API на стороне сервера. Внесите Http-сервис в компонент или другую службу. Рассмотрим этот фрагмент, который делает вызов GET на URL Википедии. Здесь http является объектом Http в @ angular / http
this.http
.get(“https://dinosaur-facts.firebaseio.com/dinosaurs.json”)

Функция get () возвращает observable. Он помогает асинхронно возвращать данные в функцию callback вызова. В отличие от промиса, observable поддерживает поток данных. Он не закрывается, как только данные возвращаются. Более того, он может быть возвращен до тех пор, пока observable явно не будет закрыт. Observable поддерживают несколько операторов или цепочку операторов. Рассмотрим оператор отображения, ниже которого JSON извлекается из ответа HTTP.
this.http
.get(“http://localhost:3000/dino”)
.map((response) => response.json())

Примечание. Здесь показан один из способов импорта оператора map.
import ‘rxjs/add/operator/map’; // Preferred way to import

В противном случае мы можем использовать следующий оператор импорта для всей библиотеки rxjs. import ‘rxjs’; Тем не менее, он все еще возвращает observable. У observable есть функция подписки, которая принимает три обратных вызова. a) Callback успеха, который имеет data input b) Error callback с input’ом ошибки c) Полный callback, который вызывается при завершении observable. Рассмотрим следующий фрагмент,
this.http
.get(“https://dinosaur-facts.firebaseio.com/dinosaurs.json”)
.map((response) => response.json())
.subscribe((data) => console.log(data), // success
(error) => console.error(error), // failure
() => console.info(“done”)); // done

Вы можете установить observable результат в переменную класса / компонента и отобразить ее в шаблоне. Лучшим вариантом будет использование async-пайпа в шаблоне. Вот пример:

dino: Observable<any>; // объявление переменной уровня класса

this.dino = this.http // Set returned observable to a class variable
.get("https://dinosaur-facts.firebaseio.com/dinosaurs.json")
.map((response) => response.json());

В шаблоне используйте async-пап. Когда объект dino доступен, используйте поля на объекте.
<div>{{ (dino |async)?.bruhathkayosaurus.appeared }}</div>

Отвезите меня к Promises обратно!
Мы можем использовать оператор RxJS для преобразования наблюдаемого в promise. Если API в настоящее время возвращает promise, для обратной совместимости это полезный оператор. Импорт toPromise оператора:
import ‘rxjs/add/operator/toPromise’;
Используйте toPromise на observable:
getData(): Promise<any>{
return this.http
.get(“https://dinosaur-facts.firebaseio.com/dinosaurs.json”)
.map((response) => response.json())
.toPromise();
}

Используйте данные, возвращенные при callback’е. Установите его в переменную класса, которая будет использоваться в шаблоне.
this.getData()
.then((data) => this.dino = data)
.catch((error) => console.error(error));

Просмотрите следующий шаблон:
<div *ngIf=”dino”>
<div>Bruhathkayosaurus appeared {{ dino.bruhathkayosaurus.appeared }} years ago</div>
</div>

Маршрутизатор (Route)
Маршрутизация позволяет создать SPA (одностраничное приложение). Используя конфигурацию маршрутизатора, компоненты сопоставляются с URL-адресом. Чтобы начать работу с Angular приложением, поддерживающим маршрутизацию с использованием Angular CLI, выполните следующую команду.
ng new sample-application –routing

Чтобы добавить модуль с маршрутизацией в существующее приложение с помощью функции Angular CLI, выполните следующую команду.
ng g module my-router-module –routing

Выход маршрутизатора
Компоненты на маршруте (URL) отображаются ниже роутера. В общем случае RouterOutlet помещается в корневой компонент для работы маршрутизации.
<router-outlet></router-outlet>

Конфигурация маршрутизации
Создайте объект маршрута типа Routes (в пакете @ angular / router), который представляет собой массив маршрутов объектов JSON. Каждый объект может иметь одно или несколько из следующих полей. path: Указывает путь для соответствия компонент: на данном пути данный компонент будет загружаться ниже маршрутизатора-выхода redirectTo: перенаправляет на заданный путь, когда путь совпадает. Например, он может перенаправляться на родину, если не указан путь. pathMatch: позволяет настраивать стратегию соответствия пути. Когда заданное значение full, полный путь должен соответствовать. В то время как префикс позволяет сопоставить начальную строку. Префиксом является значение по умолчанию. Рассмотрим следующую конфигурацию маршрута для образца:

const routes: Routes = [
{
path: 'home',
component: Sample1Component,
},
{
path: 'second2',
component: Sample2Component
},
{
path: '',
redirectTo: '/home',
pathMatch: 'full'
}
];

Дочерние маршрутизаторы (child routes)
Для конфигурации дочерних маршрутов используйте детей в объекте маршрута. Дочерний компонент отображается на маршрутизаторе-выходе в данном компоненте. Следующий образец отображает Sample1Component. Он имеет роутер-выход в шаблоне. Sample2Component отображается ниже.

const routes: Routes = [
{
path: 'home',
component: Sample1Component,
children: [
{
path: 'second',
component: Sample2Component
}
]
}… // rest of the configuration.

// Template for Sample1Component

<div>
sample-1 works!
<router-outlet></router-outlet> <!--Sample2Component отрендериться под ним -->
</div>

Параметры
Обмен данными между маршрутами осуществляется с помощью параметров URL. Настроить переменную в маршруте. В приведенном ниже примере маршрут сведений ожидает идентификатор в качестве параметра в URL-адресе. Пример

http://sample.com/details/10
{
path: details/:id,
component: DetailsComponent
}

Прочитайте значение из URL: Import ActivatedRoute из @ angular/router. Ввести ActivatedRoute и параметры доступа. Наблюдается читаемое значение из URL-адреса, как показано в примере:

// inject activatedRoute
constructor(private activeRoute: ActivatedRoute) { }

// Read value from the observable
this.activeRoute
.params
.subscribe((data) => console.log(data[id]));

Вывод
Angular JavaScript фреймворк развивается очень быстро. Из структуры MV * в AngularJS 1.x она стала основой, которая подходит к разработке пользовательского интерфейса с компонентами многократного использования. С Angular 2 и выше (текущая версия 5.x) производительность улучшилась, и новые функции постоянно добавляются. Новые версии называются просто Angular, а не квалификацией с номером версии. Angular с TypeScript имеет множество функций, которые ускоряют и упрощают разработку в JavaScript. В статье описаны некоторые из возможностей, с которых можно начать разработку на Angular. Счастливого кодирования с супер-героическим фреймворком Angular!

> Автор оригинала: Keerti Kotaru работает над веб-приложениями уже более 15 лет. Он начал свою карьеру в качестве разработчика ASP.Net, C #, JavaScript. Keerti также является Microsoft MVP, автором книги под названием «Реализация material дизайна с использованием AngularJS и одним из организаторов группы Meetg для «AngularJS Hyderabad». Его деятельность в сообществе разработчиков предполагает участие в CSI, GDG и ngHyderabad.
> Оригинал статьи на английском
Отставить отзыв

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