Spec-Zone.ru › Angular 2

Обзор архитектуры

Основные строительные блоки приложений Angular.

Angular — это фреймворк для разработки клиентских приложений на HTML и JavaScript или на языке, таком как TypeScript, который компилируется в JavaScript.

Фреймворк состоит из нескольких библиотек, некоторые из которых являются основными, а некоторые — необязательными.

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

Затем вы запускаете приложение, инициализируя корневой модуль. Angular берёт на себя управление, отображая содержимое вашего приложения в браузере и реагируя на пользовательские действия в соответствии с предоставленными вами инструкциями.

Конечно, это не всё. Подробности вы узнаете на следующих страницах. Сейчас сосредоточьтесь на общей картине.

overview

Диаграмма архитектуры определяет восемь основных строительных блоков приложения Angular:

  • Модули
  • Компоненты
  • Шаблоны
  • Метаданные
  • Привязка данных
  • Директивы
  • Сервисы
  • Инъекция зависимостей

Изучив эти строительные блоки, вы сможете приступить к работе.

Код, упомянутый на этой странице, доступен в виде живого примера.

Модули

Component

Приложения Angular модульные, и Angular имеет собственную систему модульности, называемую модулями Angular или NgМодулями.

Модули Angular — важная часть. Эта страница знакомит вас с модулями; подробная информация о них содержится на странице модулей Angular.

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

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

Модуль Angular, будь то корневой или модуль функциональности, представляет собой класс с @NgModule декоратором.

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

NgModule — это функция декоратора, которая принимает один объект метаданных, свойства которого описывают модуль. Наиболее важные свойства:

  • declarations — классы представления, которые принадлежат этому модулю. Angular имеет три вида классов представления: компоненты, директивы и каналы.

  • exports — подмножество объявлений, которые должны быть видимыми и доступными в шаблонах компонентов шаблонов других модулей.

  • imports — другие модули, чьи экспортированные классы необходимы для шаблонов компонентов, объявленных в этом модуле.

  • providers — создатели сервисов, которые этот модуль добавляет в глобальную коллекцию сервисов; они становятся доступными во всех частях приложения.

  • bootstrap — основное представление приложения, называемое корневым компонентом, которое содержит все другие представления приложения. Только корневой модуль должен задавать это bootstrap свойство.

Вот простой корневой модуль:

src/app/app.module.ts

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
@NgModule({
  imports:      [ BrowserModule ],
  providers:    [ Logger ],
  declarations: [ AppComponent ],
  exports:      [ AppComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

export AppComponent — просто демонстрация экспорта; в этом примере это не обязательно. Корневой модуль не должен экспортировать ничего, поскольку другим компонентам не нужно импортировать корневой модуль.

Запустите приложение, инициализируя его корневой модуль. Во время разработки вы, скорее всего, будете инициализировать AppModule в файле main.ts , таком как этот.

src/main.ts

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';

platformBrowserDynamic().bootstrapModule(AppModule);

Модули Angular по сравнению с модулями JavaScript

Модуль Angular — класс, снабжённый @NgModule декоратором — является фундаментальной частью Angular.

JavaScript также имеет собственную систему модулей для управления наборами JavaScript-объектов. Она совершенно другая и не связана со системой модулей Angular.

В JavaScript каждый файл является модулем, и все объекты, определённые в файле, принадлежат этому модулю. Модуль объявляет некоторые объекты общедоступными, помечая их ключевым словом export. Другие модули JavaScript используют заявления import для доступа к общедоступным объектам из других модулей.

import { NgModule }     from '@angular/core';
import { AppComponent } from './app.component';
export class AppModule { }

Узнайте больше о системе модулей JavaScript в сети.

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

Библиотеки Angular

Component

Angular поставляется в виде набора JavaScript-модулей. Их можно рассматривать как модули библиотек.

Название каждой библиотеки Angular начинается с префикса @angular.

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

Например, импортируйте декоратор Component Angular из библиотеки @angular/core так:

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

Вы также импортируете модули Angular из библиотек Angular с помощью JavaScript-заявлений import:

import { BrowserModule } from '@angular/platform-browser';

В примере простого корневого модуля модуль приложения нуждается в материалах из этой BrowserModule. Для доступа к этому материалу добавьте его в @NgModule метаданные imports следующим образом.

imports:      [ BrowserModule ],

Таким образом, вы используете обе системы модулей Angular и JavaScript совместно.

Легко перепутать эти две системы, потому что у них есть общая терминология «импорт» и «экспорт». Не паникуйте. Спустя время и опыт это станет яснее.

Узнайте больше на странице модулей Angular.

Компоненты

Component

Компонент управляет участком экрана, называемым представлением.

Например, следующие представления управляются компонентами:

  • Корневой элемент приложения с ссылками на навигацию.
  • Список героев.
  • Редактор героя.

Вы определяете логику приложения компонента — то, что он делает для поддержки представления — внутри класса. Класс взаимодействует с представлением через API свойств и методов.

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

src/app/hero-list.component.ts (класс)

export class HeroListComponent implements OnInit {
  heroes: Hero[];
  selectedHero: Hero;

  constructor(private service: HeroService) { }

  ngOnInit() {
    this.heroes = this.service.getHeroes();
  }

  selectHero(hero: Hero) { this.selectedHero = hero; }
}

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

Шаблоны

Template

Вы определяете представление компонента с помощью связанного с ним шаблона. Шаблон — это форма HTML, которая сообщает Angular, как отобразить компонент.

Шаблон выглядит как обычный HTML, за исключением нескольких отличий. Вот шаблон для нашего HeroListComponent:

src/app/hero-list.component.html

<h2>Hero List</h2>

<p><i>Pick a hero from the list</i></p>
<ul>
  <li *ngFor="let hero of heroes" (click)="selectHero(hero)">
    {{hero.name}}
  </li>
</ul>

<hero-detail *ngIf="selectedHero" [hero]="selectedHero"></hero-detail>

Хотя этот шаблон использует типичные HTML-элементы, такие как <h2> и <p>, он также имеет некоторые отличия. Код, например, *ngFor, {{hero.name}}, (click), [hero], и <hero-detail> использует синтаксис шаблонов Angular.

В последней строке шаблона тег <hero-detail> — это пользовательский элемент, представляющий новый компонент HeroDetailComponent.

HeroDetailComponent — это другой компонент, чем HeroListComponent , который вы рассматривали. HeroDetailComponent (код не показан) отображает сведения о конкретном герое, герое, который пользователь выбирает из списка, представленного HeroListComponent . HeroDetailComponent — это дочерний элемент HeroListComponent.

Metadata

Обратите внимание, как <hero-detail> удобно размещается среди стандартных HTML-элементов. Пользовательские компоненты естественно встраиваются в макеты с обычными HTML-элементами.

Метаданные

Metadata

Метаданные сообщают Angular, как обработать класс.

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

В действительности, HeroListComponent действительно просто класс. Он не является компонентом до тех пор, пока вы не сообщите об этом Angular.

Чтобы сообщить Angular, что HeroListComponent — это компонент, прикрепите метаданные к классу.

В TypeScript вы добавляете метаданные с помощью декоратора. Вот некоторые метаданные для HeroListComponent:

src/app/hero-list.component.ts (метаданные)

@Component({
  selector:    'hero-list',
  templateUrl: './hero-list.component.html',
  providers:  [ HeroService ]
})
export class HeroListComponent implements OnInit {
/* . . . */
}

Вот декоратор @Component , который идентифицирует класс непосредственно под ним как класс компонента.

Декоратор @Component требует объекта конфигурации с информацией, необходимой Angular для создания и отображения компонента и его представления.

Вот несколько наиболее полезных @Component параметров конфигурации:

  • selector: CSS-селектор, который сообщает Angular о создании и вставке экземпляра этого компонента там, где он находит тег <hero-list> в родительском HTML. Например, если HTML приложения содержит <hero-list></hero-list>, то Angular вставляет экземпляр представления HeroListComponent между этими тегами.

  • templateUrl: модульно-относительный адрес HTML-шаблона этого компонента, показанный выше.

  • providers: массив провайдеров инъекции зависимостей для служб, которые необходимы компоненту. Это один из способов сообщить Angular, что конструктор компонента требует HeroService, чтобы получить список героев для отображения.
Metadata

Метаданные в @Component сообщают Angular, где получить основные строительные блоки, которые вы определяете для компонента.

Шаблон, метаданные и компонент вместе описывают представление.

Добавляйте другие декораторы метаданных аналогичным образом, чтобы направить поведение Angular. @Injectable, @Input, и @Output — это некоторые из наиболее популярных декораторов.

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

Привязка данных

Без фреймворка вы бы отвечали за передачу значений данных в HTML-элементы управления и преобразование ответов пользователей в действия и обновления значений. Написание такой логики push/pull вручную утомительно, подвержено ошибкам и трудно читаемо, как могут подтвердить опытные программисты jQuery.

Data Binding

Angular поддерживает привязку данных — механизм для координации частей шаблона с частями компонента. Добавьте разметку привязки в HTML-шаблон, чтобы сообщить Angular, как соединить обе стороны.

Как показывает диаграмма, существует четыре формы синтаксиса привязки данных. Каждая форма имеет направление — в DOM, из DOM или в обоих направлениях.

В шаблоне HeroListComponent пример есть три формы:

src/app/hero-list.component.html (binding)

<li>{{hero.name}}</li>
<hero-detail [hero]="selectedHero"></hero-detail>
<li (click)="selectHero(hero)"></li>
  • {{hero.name}} Интерполяция отображает значение свойства hero.name компонента внутри элемента <li>.

  • [hero] Привязка свойства передает значение selectedHero из родительского HeroListComponent свойству hero дочернего HeroDetailComponent.

  • (click) Привязка события вызывает метод selectHero компонента, когда пользователь нажимает имя героя.

Двухсторонняя привязка данных — важная четвертая форма, которая объединяет привязку свойства и события в одной записи, используя директиву ngModel. Вот пример из шаблона HeroDetailComponent.

src/app/hero-detail.component.html (ngModel)

<input [(ngModel)]="hero.name">

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

Angular обрабатывает все привязки данных один раз за цикл события JavaScript, от корневого компонента приложения до всех дочерних компонентов.

Data Binding

Привязка данных играет важную роль в общении между шаблоном и его компонентом.

Parent/Child binding

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

Директивы

Parent child

Шаблоны Angular — динамичны. При рендеринге Angular преобразует DOM в соответствии с инструкциями, предоставленными директивами.

Директива — это класс с декоратором @Directive. Компонент — это директива с шаблоном; декоратор @Component фактически является декоратором @Directive, расширенным функциями, ориентированными на шаблоны.

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

Существуют два других типа директив: структурные и атрибутивные директивы.

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

Структурные директивы изменяют макет, добавляя, удаляя и заменяя элементы в DOM.

Шаблон примера использует две встроенные структурные директивы:

src/app/hero-list.component.html (structural)

<li *ngFor="let hero of heroes"></li>
<hero-detail *ngIf="selectedHero"></hero-detail>
  • *ngFor сообщает Angular о создании одного <li> на каждый герой в списке heroes.
  • *ngIf включает компонент HeroDetail только в том случае, если выбран герой.

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

Директива ngModel, реализующая двухстороннюю привязку данных, является примером атрибутивной директивы. ngModel изменяет поведение существующего элемента (обычно <input>), устанавливая его свойство значения отображения и реагируя на события изменений.

src/app/hero-detail.component.html (ngModel)

<input [(ngModel)]="hero.name">

Angular имеет несколько других директив, которые либо изменяют структуру макета (например, ngSwitch), либо изменяют аспекты элементов DOM и компонентов (например, ngStyle и ngClass).

Конечно, вы также можете писать свои собственные директивы. Компоненты, такие как HeroListComponent — это один из видов пользовательских директив.

Сервисы

Service

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

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

Примеры включают:

  • служба регистрации
  • служба данных
  • мессенджер
  • калькулятор налогов
  • конфигурация приложения

В службах нет ничего специфически Angular. У Angular нет определения службы. Нет базового класса службы и нет места для регистрации службы.

Тем не менее, службы являются основополагающими для любого приложения Angular. Компоненты являются большими потребителями служб.

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

src/app/logger.service.ts (class)

export class Logger {
  log(msg: any)   { console.log(msg); }
  error(msg: any) { console.error(msg); }
  warn(msg: any)  { console.warn(msg); }
}

Вот HeroService, который использует Promise для получения героев. HeroService зависит от службы Logger и другой службы BackendService, которая выполняет вспомогательную работу по общению с сервером.

src/app/hero.service.ts (class)

export class HeroService {
  private heroes: Hero[] = [];

  constructor(
    private backend: BackendService,
    private logger: Logger) { }

  getHeroes() {
    this.backend.getAll(Hero).then( (heroes: Hero[]) => {
      this.logger.log(`Fetched ${heroes.length} heroes.`);
      this.heroes.push(...heroes); // fill cache
    });
    return this.heroes;
  }
}

Сервисы повсюду.

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

Задача компонента — обеспечить пользовательский опыт и ничего более. Он выступает в качестве посредника между представлением (отображаемым шаблоном) и логикой приложения (которая часто включает некоторое понятие модели). Хороший компонент предоставляет свойства и методы для привязки данных. Он делегирует все нетривиальные задачи службам.

Angular не обязывает следовать этим принципам. Он не будет жаловаться, если вы напишете компонент «все в одном» объемом в 3000 строк.

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

Инъекция зависимостей

Service

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

Angular может определить, какие службы необходимы компоненту, посмотрев на типы параметров его конструктора. Например, конструктор вашего HeroListComponent нуждается в HeroService:

src/app/hero-list.component.ts (constructor)

constructor(private service: HeroService) { }

При создании компонента Angular сначала запрашивает у инжектора службы, которые необходимы компоненту.

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

Процесс HeroService инъекции выглядит примерно так:

Service

Если инжектор не имеет HeroService, как он знает, как его создать?

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

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

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

src/app/app.module.ts (module providers)

providers: [
  BackendService,
  HeroService,
  Logger
],

В качестве альтернативы, зарегистрируйте на уровне компонента в свойстве providers метаданных @Component:

src/app/hero-list.component.ts (component providers)

@Component({
  selector:    'hero-list',
  templateUrl: './hero-list.component.html',
  providers:  [ HeroService ]
})

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

Основные моменты, касающиеся инъекции зависимостей:

  • Инъекция зависимостей интегрирована в фреймворк Angular и используется повсюду.

  • Инжектор — основной механизм.

    • Инжектор хранит контейнер экземпляров сервисов, которые он создал.
    • Инжектор может создать новый экземпляр сервиса из провайдера.
  • Провайдер — рецепт создания сервиса.

  • Регистрируйте провайдеры в инжекторах.

Заключение

Вы узнали основы восьми основных строительных блоков приложения Angular:

  • Модули
  • Компоненты
  • Шаблоны
  • Метаданные
  • Привязка данных
  • Директивы
  • Сервисы
  • Инъекция зависимостей

Это основа всего остального в приложении Angular, и этого достаточно, чтобы начать работу. Но это не всё, что нужно знать.

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

Анимации: Анимируйте поведение компонентов без глубокого знания анимационных техник или CSS с помощью библиотеки анимаций Angular.

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

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

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

HTTP: Связывайтесь с сервером, чтобы получать данные, сохранять данные и вызывать действия на стороне сервера с помощью HTTP-клиента.

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

Фильтры: Используйте фильтры в своих шаблонах для улучшения пользовательского опыта путём преобразования значений для отображения. Рассмотрим выражение фильтра currency:

price | currency:'USD':true

Оно отображает цену 42.33 как $42.33.

Маршрутизатор: Перемещайтесь от страницы к странице в приложении клиента и не покидайте браузер.

Тестирование: Запускайте модульные тесты на частях приложения по мере их взаимодействия с фреймворком Angular, используя платформу тестирования Angular.

Следующий шаг

AppModule: корневой модуль

© 2010–2017 Google, Inc.
Licensed under the Creative Commons Attribution License 4.0.
https://v2.angular.io/docs/ts/latest/guide/architecture.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API