Статьи

Начало работы с Angular 2 с использованием TypeScript

Эта статья основана на альфа-версии Angular 2, которая сейчас устарела. Актуальное руководство см. В статье Angular 2 Tutorial: создание приложения CRUD с Angular CLI .

Текущая стабильная версия Angular (то есть Angular 1.x) была построена с использованием функций ES5 и предназначалась для работы на большинстве браузеров, включая некоторые из более старых версий IE. Фреймворк должен был создать собственную систему модулей, абстрагировать некоторые языковые функции и обеспечить интерфейс для работы с абстракцией и конфигурацией.

Все хорошие вещи Angular 1 по-прежнему доступны в Angular 2, но рамки проще. Angular 2 построен с учетом особенностей ES6 (и ES7), веб-компонентов и предназначен для вечнозеленых браузеров.

TypeScript — это типизированный супер-набор JavaScript, созданный и поддерживаемый Microsoft и выбранный группой разработчиков AngularJS для разработки. Наличие типов делает код, написанный на TypeScript, менее подверженным ошибкам во время выполнения. В последнее время поддержка ES6 была значительно улучшена, а также были добавлены некоторые функции от ES7.

В этой статье мы увидим, как использовать Angular 2 и TypeScript для создания простого приложения. Поскольку Angular 2 все еще находится в альфа-версии, синтаксис фрагментов кода, показанных в этой статье, может измениться, прежде чем он достигнет стабильной версии. Код, разработанный в этой статье, доступен на GitHub .

Основы Angular 2

Angular 2 был построен с учетом простоты. Команда удалила несколько рецептов Angular 1, которые заставили нас задуматься: «Зачем мы это делаем?» (Если вы хотите узнать, что было удалено, я предлагаю вам взглянуть на это видео под названием « Angular 2.0 Core session» от Igor). и Тобиас ). Теперь структура состоит из небольшого набора строительных блоков и некоторых соглашений, которым необходимо следовать.

Строительные блоки, которые присутствуют в Angular 2:

  1. Компоненты: Компонент похож на директивы в Angular 1. Он построен с использованием функций веб-компонентов. Каждый компонент имеет представление и часть логики. Он может взаимодействовать со службами для достижения своей функциональности. Сервисы могут быть «внедрены зависимостями» в компонент. Все, что должно использоваться с учетом компонента, должно быть открытым членом в экземпляре компонента. Компоненты используют привязку свойств, чтобы проверять изменения значений и воздействовать на них. Компоненты могут обрабатывать события, а обработчики событий являются открытыми методами, определенными в классе компонента.
  2. Сервисы: Сервис — это простой класс ES6 с некоторыми аннотациями для внедрения зависимостей.

Как и в Angular 1, Angular 2 использует Dependency Injection для получения ссылок на объекты. Поскольку scope Следовательно, нам не нужно продолжать вызывать scope.$apply Angular 2 использует Zone.js для запуска изменений, и эта библиотека знает, когда действовать.

Приложение Angular 2 запускается с компонента, а остальная часть приложения разделена на несколько компонентов, которые загружаются внутри корневого компонента.

Если вы хотите узнать больше об основах Angular 2, ознакомьтесь с публикацией в блоге Виктора Савкина об основных понятиях в Angular 2 .

Настройка

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

Существует множество начальных проектов, которые можно начать с Angular 2 и TypeScript. Я думаю, что этот Elad Katz мог бы стать хорошей отправной точкой для некоторой практики. Для начала, если вы хотите следовать этому уроку, клонируйте этот репозиторий. Затем следуйте инструкциям, указанным в readme

Репозиторий:

  • содержит базовое приложение Angular 2 с использованием TypeScript
  • использует JSPM / SystemJS для загрузки зависимостей на страницах
  • ссылается на файлы определений TypeScript библиотек, использующих TSD, и определяет отсутствующие определения Angular 2 в локальном файле angular2.temp.d.ts
  • вызывает API Express REST для использования в Angular
  • использует Gulp для переноса кода TypeScript на ES5 и запуска сервера Node.js
  • содержит исходные файлы TypeScript, которые находятся внутри папки сценариев, а общая папка используется для хранения передаваемых файлов.

Как закрепить ваши достижения

Построение Express API

Теперь, когда у вас есть представление о том, что такое Angular 2, и вы также клонировали начальный проект, давайте изменим его. Мы создадим простое приложение, чтобы закрепить ваши достижения на доске. Прежде всего, давайте добавим Express API для получения и добавления достижений. Когда я разветвил репозиторий и изменил начальный проект, добавив базовые API-интерфейсы Express, вы увидите конечную точку, обслуживающую существующий список всех достижений. Чтобы опубликовать новое достижение, нам нужно добавить конечную точку.

Чтобы выполнить эту первую задачу, откройте файл server.js

 app.post('/api/achievements', function(request, response){
    achievements.push(JSON.parse(request.body));
    response.send(achievements);
});

Поскольку Http Итак, давайте добавим промежуточное ПО bodyParser

 app.use(bodyParser.text({
   type: 'text/plain'
}));

Модификация компонента запуска и маршрутов

Файл index.html Основная часть этого файла загружает скрипт bootstrapmy-app Этот компонент в свою очередь загружает другие компоненты в приложение. Файл bootstrap.ts загружает приложение AngularJS с использованием основного компонента. Как видите, необходимые функции для инъекций, экспортируемые другими модулями, передаются в функцию. Это делает службы и директивы, экспортируемые этими модулями, доступными для всех дочерних компонентов bootstrap.ts Мы будем использовать my-appformformInjectables

 angular2/forms

Компонент запуска проекта находится внутри папки import {formInjectables} from 'angular2/forms';
bootstrap(MyApp, [routerInjectables, httpInjectables, formInjectables, AchievementsService]);
К компоненту применены две аннотации:

  1. Компонент: содержит свойства конфигурации компонента, такие как селектор, имена свойств, имена событий и список инъекций в компонент. Значение селектора может совпадать со строкой, используемой в разметке HTML, его не нужно обрабатывать верблюдом
  2. Представление: аннотация представления загружает данные, необходимые для части представления компонента. Он включает в себя шаблон HTML (может быть встроенным или URL-адрес шаблона) и список директив, в которых нуждается компонент

Ниже вы можете увидеть соответствующий код:

 app

Компонент @Component({
selector: 'my-app'
})
@View({
templateUrl: _settings.buildPath + '/components/app/app.html',
directives: [RouterLink, RouterOutlet]
})
Сервис my-appRouter Следующий фрагмент определяет два маршрута, необходимые для приложения:

 MyApp

Поскольку компонент добавления еще не добавлен, вы столкнетесь с некоторыми проблемами, если попытаетесь запустить приложение сейчас. Нам нужно создать новую папку внутри папки компонентов и назовите ее export class MyApp {
constructor(@Inject(Router) router: Router) {
router.config([
{ path: '', as: 'home', component: Home },
{ path: '/add', as: 'add', component: Add }
]);
}
}
Затем мы добавляем в эту папку два файла: addadd Наконец, добавьте следующий фрагмент в add.ts

 add.html

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

 add.ts file

В представлении нам нужно создать ссылки для навигации между страницами. Компонент атрибута import {Component, View} from 'angular2/angular2';
import { _settings } from '../../settings'
import {FormBuilder, Validators, formDirectives, ControlGroup} from 'angular2/forms';
import {Inject} from 'angular2/di';
import {Router} from 'angular2/router';
import {AchievementsService} from '../../services/achievementsService';

@Component({
selector: ‘add’,
injectables: [FormBuilder]
})
@View({
templateUrl: _settings.buildPath + ‘/components/add/add.html’,
directives:[formDirectives]
})
export class Add {
} Нам нужно присвоить имя компонента атрибуту, и он позаботится о создании ссылки на основе пути, предварительно настроенного для компонента.

 <div>Add New Achievement</div>
<br />
<form>
  <div class="input-group">
    <span>Title</span>
    <input type="text" id="title" class="form-control" />
  </div>
  <div class="input-group">
    <span>Type</span>
    <input type="text" id="type" class="form-control" />
  </div>
  <div class="input-group">
    <span>From</span>
    <input type="text" id="from" class="form-control" />
  </div>
  <div>&nbsp;</div>
  <div class="input-group">
    <input type="submit" value="click" class="btn btn-primary" />
    <input type="reset" value="Reset" class="btn" >
  </div>
</form>

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

 <ul class="nav navbar-nav">
  <li>
    <a router-link="home">Home</a>
  </li>
  <li>
    <a router-link="add">Add</a>
  </li>
</ul>

Перечисление всех достижений

Теперь давайте изменим домашний компонент, чтобы отобразить список всех достижений в виде закрепленных блоков на стене. Мы будем использовать Bootstrap для стилизации этой страницы. CSS Bootstrap уже загружен в route-outlet

Прежде чем приступить к работе с пользовательским интерфейсом, давайте создадим сервис для отправки запросов Ajax в API Express.js для взаимодействия с данными. У нас есть файл с именем <router-outlet></router-outlet> Переименуйте его в качестве index.htmldummyService Добавьте следующий код в этот файл. Этот фрагмент кода настраивает внедрение зависимостей для службы и добавляет метод для получения всех достижений от службы:

 achievementsService

Методы класса AchievementsService Последние являются объектами, которые имеют встроенные возможности для уведомления, когда что-то меняется. import {Component, View} from 'angular2/angular2';
import { Inject} from 'angular2/di';
import {Http} from 'angular2/http';

export class AchievementsService {
constructor( @Inject(Http) private http: Http) {
}

getAllAchievements(): any {
var path = ‘/api/achievements’;
return this.http.get(path);
}
}HttpAchievementsService

Чтобы продолжить работу с проектом, замените код в NgFor

 home.ts import {Component, View, NgFor} from 'angular2/angular2';
import { _settings } from '../../settings'
import {AchievementsService} from '../../services/achievementsService';
import {Inject} from 'angular2/di';

@Component({
  selector: 'home',
  injectables: [AchievementsService]
})
@View({
  templateUrl: _settings.buildPath + "/components/home/home.html",
  directives: [NgFor]
})
export class Home {
  achievements: Array;

  constructor( @Inject(AchievementsService) private achievementsService: AchievementsService) {
    achievementsService.getAllAchievements()
      .map(r => r.json())
      .subscribe(a => {
        this.achievements = a;
      });
  }
} 

Обратный вызов подписки, добавленный в приведенный выше фрагмент, вызывается после того, как наблюдаемое отправляет уведомление. Зоны понимают, как работают наблюдаемые, и обновляют интерфейс после того, как наблюдаемое установило значение. Разметка в файле home.html

 <div class="row">
  <div *ng-for="#achievement of achievements" class="thumbnail col-md-3 col-sm-3 col-lg-3">
    <span class="glyphicon glyphicon-pushpin"></span>
    <div class="caption">
      <strong>{{achievement.title}}</strong>
    </div>
    <p class="text-center">Level: {{achievement.type}}</p>
    <p class="text-center">From: {{achievement.from}}</p>
  </div>
</div>

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

  • Символ звездочки перед ng-forшаблон
  • Символ хеша перед достижением переменной записи делает его локальной переменной. Может использоваться внутри шаблона для привязки данных

Давайте сохраним эти изменения и запустим приложение. Вы увидите список достижений в виде ящиков.

дом

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

У нас должна быть form Добавьте следующий метод в AchievementsService

 addAnAchievement(newAchievement) {
  var path = '/api/achievements';
  return this.http.post(path, JSON.stringify(newAchievement));
}

Представление add

  • Примите значения в форме и отправьте их на сервер Express
  • Как только значение будет успешно введено, перенаправьте пользователя на главный экран

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

В подходе, основанном на модели, нам нужно создать объект модели, который будет привязан к форме, и декларативно прикрепить его к форме. Поля в форме связаны со свойствами объекта модели. Значение объекта модели передается службе для отправки на сервер.

Следующий шаг, который вам нужно выполнить, это открыть файл add.tsAdd

 addAchievementForm: any;

constructor( @Inject(FormBuilder) private formBuilder: FormBuilder,
    @Inject(Router) private router: Router,
    @Inject(AchievementsService) private achievementsService: AchievementsService) {
  this.addAchievementForm = formBuilder.group({
    title: [''],
    type: [''],
    from: ['']
  });
}

addAchievement() {
  this.achievementsService.addAnAchievement(this.addAchievementForm.value)
    .map(r => r.json())
    .subscribe(result => {
      this.router.parent.navigate('/');
    });
}

Свойство addAchievementForm Свойства этого объекта будут прикреплены к элементам управления внутри формы с помощью директивы ng-control Метод addAchievement

Возможно, вы заметили, что мы не обрабатываем случаи ошибок HTTP-запросов. Это потому, что эта функция еще не доступна в HTTP API, но, безусловно, она станет лучше в будущем.

Теперь откройте файл app.html

 <form (ng-submit)="addAchievement()" [ng-form-model]="addAchievementForm">

В приведенном выше фрагменте скобки вокруг ng-submit Назначенная ей функция будет вызываться, когда form Квадратные скобки вокруг директивы ng-form-model

Теперь единственное ожидающее изменение — это присоединение полей объекта модели к элементам управления вводом. Следующий фрагмент показывает измененное текстовое поле ввода для заголовка и соответственно изменяет другие элементы управления:

 <input type="text" id="title" ng-control="title" class="form-control" />

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

Выводы

Angular 2 охватывает новейшие и лучшие технологии переднего мира. Кроме того, использование TypeScript для написания кода повышает производительность разработчиков. Как мы уже видели, фреймворк полностью переписан и помогает вам делать многие вещи более простым способом. Поскольку фреймворк все еще находится в альфа-версии, я предлагаю вам не использовать его в приложении, которое находится в производстве. Будьте терпеливы и подождите, чтобы увидеть, как команда AngularJS формирует своего ребенка.