Angular vs Angular 2: ключевые различия

в 11:10, , рубрики: angular, angular2, AngularJS, TypeScript

Мы в команде Web Development компании Itransition уже имеем хороший опыт разработки на Angular 2 и хотим им поделиться.

Эта статья ориентирована на тех крутых ребят, которые разрабатывают на Angular и подумывают перейти на вторую его версию.

Стоит ли начинать новый проект на Angular 2?

Однозначно – да! И вот почему:

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

Начало нового проекта

Наконец-то глоток свежего воздуха, полная свобода, можно начать всё с чистого листа. Хорошенько проработать архитектуру, структуру данных, компоненты, различные абстракции, составить некий словарь терминов приложения и так далее. Чтобы всё было красиво.

Свобода действий

Но с первой версией Angular не всё так просто. Нужно чтобы всё придуманное ложилось на реалии фреймворка, его модули и сервисы строго определенного типа. Нельзя просто так взять и аккуратно создать некий класс или компонент, который будет делать что-то важное. Нужно решить, чем этот компонент будет с точки зрения фреймворка? Каким типом сервиса: «value», «constant» или всё же «factory»? А может быть сервис типа «service»? Ведь он создаёт объект с оператором new, вроде бы это то, что нужно. А вдруг синглтона будет недостаточно? И эти вопросы возникают практически всегда, работая с Angular, в подобных ситуациях, и нет на них однозначного ответа.

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

Генератор кода

Далее для начала работы над проектом необходимо:

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

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

ng new app-name

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

Команда может принимать дополнительные аргументы. Например, если планируется использовать CSS препроцессор Stylus:

ng new app-name --style=styl

Будет автоматически настроена компиляция и сборка стилей с учётом выбранного препроцессора.

TypeScript

Сгенерированный код приложения будет использовать TypeScript, который пугает многих, скорее всего попросту из-за ошибочных представлений о нём. На самом деле это тот же JavaScript (ECMAScript 6), но с некоторыми приятными и полезными примочками:

  • интерфейсы,
  • типизация,
  • перечисления (Enum),
  • модификаторы (public, private, static),
  • декораторы (@).

Всё это позволяет писать более стабильный и красивый код, избавляет от надобности повсеместно использовать скверный JSDoc.

Начав использовать TypeScript, хочется писать только на нём, и уже не понимаешь, как можно было быть таким грешным – не использовать его раньше?

Компоненты

В Angular 2 нет контроллеров, только компоненты. Создать новый можно таким образом:

ng generate component playground/player

Эта команда создаст директорию player в playground с минимально необходимым кодом компонента:

  1. файл реализации,
  2. файл шаблона,
  3. файл стилей с расширением используемого CSS препроцессора,
  4. файл юнит-тестов.

Никаких копипастов — источника зла и ошибок! Сгенерированный код реализации компонента будет такой:

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

@Component({
  selector: 'app-player',
  templateUrl: './player.component.html',
  styleUrls: ['./player.component.styl']
})
export class PlayerComponent implements OnInit {
  constructor() {}

  ngOnInit() {}
}

@ + Component здесь – и есть пример декоратора. В конечном счёте, это простая функция, которая получает в качестве аргумента конструктор, определённый ниже, и изменяет его с учётом описанной конфигурации, в данном случае это:

  1. selector – определяет, как будет называться элемент компонента в шаблонах приложения (<app-player></app-player>),
  2. templateUrl – путь к файлу шаблона текущего компонента,
  3. styleUrls – массив путей к файлам стилей компонента.

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

Two-way binding

Ключевая фишка Angular — two-way binding. Как она реализована в Angular 2?

<app-player [(position)]="playerPosition"></app-player>

Такая запись в шаблоне передаст значение свойства playerPosition текущего компонента и будет изменять его при изменении свойства position внутри компонента player. Это и есть two-way binding.

Но почему именно такая довольна странная запись?

В Angular 2 появился новый синтаксис, который позволяет передавать значения свойств дочерним компонентам (one-way binding). Использует он квадратные скобки:

<app-player [position]="playerPosition"></app-player>

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

<app-player (positionChange)="onPositionChange($event)"></app-player>

Такая запись подразумевает, что в компоненте player есть свойство positionChange, которое является экземпляром класса EventEmitter. И когда в компоненте player вызывается this.positionChange.emit(newValue), выполняется код onPositionChange($event), указанный в шаблоне. $event будет содержать значение newValue.

Собственно, так в Angular 2 и реализуется two-way binding:

  1. передача исходного значения свойства,
  2. подписка на событие с названием «название свойства внутри дочернего компонента» + «Change»,
  3. изменение свойства в родительском компоненте при появлении события.

А запись [(position)]=«playerPosition» является лишь синтаксическим сахаром, которая делает всё описанное автоматически и экономит время на постройку дома, посадку дерева и выращивание сына.

Благодаря этой реализации в Angular 2 нет вотчеров, которые ранее являлись источников многих проблем с производительностью. Теперь всё более естественно.

Принципы SOLID

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

Angular 2 решает множество проблем, связанных с высоким уровнем связанности кода, новой мощной реализацией Dependency Injection и возможностью абстрагироваться от реализаций различных взаимосвязанных компонентов, используя интерфейсы (TypeScript).

Например, можно написать такую конструкцию:

class SomeComponent {
	constructor(public someService: SomeService) {}
}

И при создании экземпляра этого компонента автоматически будет создан экземпляр сервиса SomeService и передан в конструктор SomeComponent. Это очень сильно снижает уровень связанности и позволяет тестировать их в отдельности друг от друга.

Так же, запись public someService (TypeScript) делает этот сервис доступным внутри экземпляра класса с помощью ключевого слова this (this.someService).

Валидация форм

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

Пример реализации формы ввода нового пароля с проверкой его сложности и подтверждением:

let passwordControl = new FormControl('', [
	Validators.required,
	CustomValidators.complexPassword,
]);

let passwordConfirmControl = new FormControl('', [
	Validators.required,
]);

this.formGroup = new FormGroup({
	password: passwordControl,
	passwordConfirm: passwordConfirmControl,
}, CustomValidators.match(passwordControl, passwordConfirmControl));

Валидатор (Validators.required и подобные) – простая функция, в которую передаётся значение и которая возвращает null или объект с описанием ошибки.

В шаблоне формы нужно указать formGroup:

<form [formGroup]="formGroup">

Полям ввода нужно указать соответствующие названия контролов formGroup:

<input type="password" formControlName="password">
<input type="password" formControlName="passwordConfirm">

И всё. Валидна ли форма, все ошибки и состояния можно получать через объект formGroup, который будет обновляться при каждом взаимодействии пользователя с ней.

Роутинг

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

{
  path: 'profile',
  loadChildren: 'app/profile/prodile.module#ProfileModule'
}

Обработка всех запросов, начинающихся с /profile (/profile/photo, /profile/orders, /profile/orders/:id), будет передана ProfileModule, который будет загружен раз при первой необходимости.

Низкий порог вхождения

В начале статьи говорилось о низком пороге вхождения. Несмотря на всю мощь Angular 2, это действительно так.

На мой взгляд, это из-за того, что:

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

Но это не говорит о лёгкости его усвоения человеком не знающего JavaScript.

Заключение

Ещё много можно написать про новую версию фреймворка, сравнить основные сервисы, разобраться, как происходит работа с асинхронными операциями (Zone.js), упомянуть о реактивном программировании (Rx.js) и так далее. Но это уже будет не статья, а целая книга.

Хочется сказать, что Angular 2 – очень профессиональный и качественный фреймворк. Работая с ним, чувствуешь, что его писали люди, которые имеют большой опыт практической разработки и понимаешь, что больше не хочется писать на первой его версии.

QuickStart

Успехов!

Автор: chuev

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js