Architektura Angular 2 - Instytut Informatyki Teoretycznej i Stosowanej

Transkrypt

Architektura Angular 2 - Instytut Informatyki Teoretycznej i Stosowanej
Architektura Angular 2
Architektura Angular 2
Tworzenie serwisów Web 2.0
dr inż. Robert Perliński
[email protected]
Politechnika Częstochowska
Instytut Informatyki Teoretycznej i Stosowanej
6 czerwca 2016
1/41
Plan prezentacji
1
Architektura Angular 2
Moduły
Komponenty
Szablony
Metadane
Wiązanie danych
Dyrektywy
Usługi
Wstrzykiwanie zależności
2
Źródła
Architektura Angular 2
2/41
Angular 2
https://angular.io/
Warto polecić:
http://www.angular2.com/ - zbiór odnośników związanych z Angular 2
https://egghead.io/technologies/angular2 - przewodnik video po Angular 2
Architektura Angular 2
3/41
Architektura Angular 2
Osiem głównych bloków konstrukcyjnych aplikacji Angular 2:
1
Moduły
2
Komponenty
3
Szablony
4
Metadane
5
Wiązanie danych
6
Dyrektywy
7
Usługi
8
Wstrzykiwane zależności
To są podstawy dla wszystkich pozostałych elementów aplikacji Angular.
Z powodzeniem wystarczą do dalszej pracy i nauki, ale nie jest to wszystko
czego będziemy potrzebować.
Architektura Angular 2
4/41
Architektura Angular 2
Angular 2:
szablon do budowania aplikacji w HTML i JavaScript,
składa się z kilku współpracujących bibliotek, niektóre są konieczne,
inne opcjonalne.
Aplikacja:
łączy szablony HTML z wstawkami z Angulara,
wykorzystuje komponenty do zarządzania tymi szablonami,
dodaje logikę aplikacji w usługach,
przekazuje nadrzędny komponent do funkcji ją uruchamiającej.
Architektura Angular 2
5/41
Architektura Angular 2
Architektura Angular 2
6/41
1.1. Moduły
Najważniejsze:
aplikacje Angular składają się z modułów,
moduły eksportują różne elementy - klasy, funkcje, wartości importowane przez inne moduły,
zalecane jest tworzenie aplikacji jako kolekcji modułów, każdy moduł
eksportuje jeden element.
Pierwszy stworzony moduł będziej najprawdopodobniej eksportował
komponent.
Architektura Angular 2
7/41
1.1. Moduły
Zwykle aplikację Angular tworzy się z wielu modułów.
Typowy moduł jest spójnym blokiem kodu przeznaczonym do jednego
celu.
Moduły eksportują coś wartościowego z tego kodu, zwykle jeden
element jak na przykład klasa.
Moduły są opcjonalne ale bardzo wskazane.
Angular sam w sobie nie wymaga modułów.
TypeScript oraz ES2015 świetnie wspierają moduły.
Dlatego właśnie moduły zostały wyróżnione jako jeden z bloków
konstrukcyjnych.
Używamy tutaj słów: import oraz export.
Architektura Angular 2
8/41
1.1. Moduły
Pierwszy moduł z jakim się spotkamy będzie prawdopodobnie eksportował
komponent. Większość aplikacji ma komponent AppComponent w pliku
app.component.ts. Taka jest przyjęta konwencja nazewnictwa.
Eksportowanie komponentu:
app/app.component.ts
export class AppComponent { }
Importowanie komponentu:
app/main.ts
import { AppComponent } from './app.component';
Nazwa modulu to nazwa pliku bez podanego rozszerzenia.
Architektura Angular 2
9/41
1.2. Biblioteki modułów
Niektóre moduły są bibliotekami innych modułów.
Angular sam w sobie jest dostarczony jako biblioteka modułów
wewnątrz kilku pakietów npm.
Ich nazwy zaczynają się od @angular.
Główna biblioteka to @angular/core. Dostarcza ona większość
wymaganej funkcjonalności.
Inne ważne biblioteki to: @angular/common, @angular/router i
@angular/http.
Architektura Angular 2
10/41
1.2. Biblioteki modułów
Importowanie elementów z bibliotek angular odbywa się tak samo jak z
naszych własnych plików: Importowanie funkcji Component:
import { Component } from '@angular/core';
Tutaj importowanie odbywa się z modułu biblioteki. Nazwa
@angular/core jest ”pusta” - bez śćieżki dostępu. W przypadku
importowania naszych własnych modułów podajemy ścieżkę dostępu.
Względny adres położenia naszego modułu podajemy zaczynając od ./.
Architektura Angular 2
11/41
2. Komponenty
Komponent kontroluje pewien stały fragment ekranu, który można
nazwać widokiem.
Menu nawigacyjne, lista bohaterów, edytor do modyfikacji danych o
bohaterach, ...
... to są wszystko widoki kontrolowane przez komponenty.
Programista definiuje logikę aplikacji wewnątrz komponentów wewnątrz
klas. Logika ta odpowiada za obsługę widoku związanego z danym
komponentem. Klasa współdziała z widokiem poprzez zbiór atrybutów i
metod (API klasy).
Architektura Angular 2
12/41
2. Komponenty
Dla przykładu komponent Bohaterowie może mieć atrybut heroes
zwracający listę bohaterów uzyskaną z jakiejś usługi. Może mieć metodę
selectHero(), która ustawia atrybut selectedHero po kliknięciu na
wybranego bohatera. Przykład:
app/hero-list.component.ts
export class HeroListComponent implements OnInit {
constructor(private service: HeroService) { }
heroes: Hero[];
selectedHero: Hero;
ngOnInit() {
this.heroes = this.service.getHeroes();
}
selectHero(hero: Hero) { this.selectedHero = hero; }
}
Angular automatycznie tworzy, aktualizuje i usuwa komponenty zgodnie z
działaniami podejmowanymi przez użytkownika aplikacji. Programista
może zdefiniować określone akcje w każdym momencie życia komponentu
poprzez wstawki programowe (ang. Lifecycle Hooks).
Architektura Angular 2
13/41
3.1. Szablony
Widok związany z każdym komponentem jest zawsze definiowany razem z
jego szablonem. Szablon to jakaś forma kodu HTML określająca jak
przedstawić komponent. Szablon wygląda jak regularny kod HTML ale ma
wstawki związane z Angular. Przykład:
Architektura Angular 2
14/41
3.1. Szablony
Szablon wygląda jak regularny kod HTML ale ma wstawki związane z
Angular. Przykład:
app/hero-list.component.html
<h2>Hero List</h2>
<p><i>Pick a hero from the list</i></p>
<div *ngFor="let hero of heroes" (click)="selectHero(hero)">
{{hero.name}}
</div>
<hero-detail *ngIf="selectedHero" [hero]="selectedHero"></hero-detail>
Oprócz klasycznego kodu HTML (znaczniki <h2>, <div>) mamy też
*ngFor, {{hero.name}}, (click), [hero], and <hero-detail>.
Architektura Angular 2
15/41
3.2. Drzewo komponentów
Element <hero-detail> reprezentuje komponent HeroDetailComponent.
To jest inny komponent niż HeroListComponent. HeroDetailComponent
jest dzieckiem komponentu HeroListComponent.
Tag <hero-detail> możemy spokojnie połączyć ze znanymi tagami z
języka HTML. W ten sposób łączymy również dyrektywy różnych
komponentów w drzewo:
Architektura Angular 2
16/41
4.1. Metadane
Metadane informują Angular jak przetwarzać klasy. Patrząc na
HeroListComponent widać, że jest to tylko klasa. Nie ma w niej nic, co
by wskazywało na użycie jakiegoś frameworka, nie ma tam nic z Angulara.
Nie jest to komponent dopókie nie poinformujemy o tym Angulara.
Informowanie Angulara, że to jest komponent odbywa się właśnie za
pośrednictwem metadanych. Najprostszym sposobem dołączenia
metadanych w języku TypeScript jest wzorzec dekorator.
Architektura Angular 2
17/41
4.1. Metadane
Mamy tutaj wykorzystany wzorzec dekorator dla komponentu
(@Component), który określa, że klasa bezpośredno pod nim występująca
jest komponentem.
app/hero-list.component.ts (metadane)
@Component({
selector:
'hero-list',
templateUrl: 'app/hero-list.component.html',
directives: [HeroDetailComponent],
providers:
[HeroService]
})
export class HeroesComponent { ... }
Dekorator jest funkcją. Bardzo często ma parametr konfiguracyjny.
Dekorator @Component przyjmuje wymagany parametr - obiekt
konfigurujący zawierający podrzebne dla Angulara informacje do
utworzenia i pokazania związanego z komponentem widoku.
Architektura Angular 2
18/41
4.1. Opcje konfiguracyjne komponentu
selector - selektor CSS, który oklreśla położenie widoku związanego z
komponentem w miejscu występowania podanego tutaj znacznika
HTML, np.: <hero-list>.
templateUrl - położenie szablonu danego komponentu.
directives - tablica komponentów albo dyrektyw wymaganych przez
ten szablon. W przypadku naszego szablonu oczekujemy, że Angular
doda komponent HeroDetailComponent w miejsce odpowiedniego
znacznika.
providers - tablica zawierająca listę usług dodawanych do
komponentu za pomocą wstrzykiwania zależności. To jest jeden ze
sposobów, żeby poinformować Angular, że nasz komponent wymaga
konkretnej listy usług.
Architektura Angular 2
19/41
4.2. Metadane - widok
Funkcja @component przyjmuje obiekt konfiguracyjny
i zamienia go w metadane, które są dołączane
do definicji klasy komponentu.
Angular rozpoznaje i odczytuje te dane
i stąd wie jak prawidłowo działać.
Szablon, metadane i komponent
razem określają widok.
W ten sam sposób stosujemy inne matadane wzorca dekorator określające
zachowanie Angulara. Niektóre z nich to: @Injectable, @Input, @Output,
@RouterConfig.
To co musimy wiedzieć o architekturze systemu, to to, że musimy dodać
metadane do naszego kodu żeby Angular wiedział co ma robić.
Architektura Angular 2
20/41
5.1. Wiązanie danych
Bez użycia szablonu aplikacji, programista jest odpowiedzialny za
przekazywanie danych do kontrolek HTML i przekształcanie działań
użytkownika na odpowiednie akcje z aktualizacją odpowiednich
danych.
Tworzenie samodzielnie takiej logiki wysyłania/pobierania jest:
żmudne, podatne na błędy i straszne w czytaniu (o czym więdzą
doświadczenie programiści pracujący z jQuery).
Angular wspiera wiązanie danych - mechanizm, który koordynuje
zawartość komponentu z przypisanym mu szablonem.
Architektura Angular 2
21/41
5.1. Wiązanie danych
Dodajemy znacznki wiązania danych do szablonu HTML, które
określają jak połączyć obie strony.
Istnieją cztery formy składni wiązania danych: do drzewa DOM, od
drzewa DOM albo w obu kierunkach.
Architektura Angular 2
22/41
5.1. Jednokierunkowe wiązanie danych
Poniższy kod przedstawia trzy formy wiązania danych:
app/hero-list.component.html (fragment)
<div>{{hero.name}}</div>
<hero-detail [hero]="selectedHero"></hero-detail>
<div (click)="selectHero(hero)"></div>
wstawianie (ang. interpolation) wyświetla właściwość hero.name
komponentu wewnątrz <div>,
wiązanie właściwości [hero] (ang. property binding ) przekazuje
wybranego bohatera (selectedHero) z nadrzędnego komponentu
HeroListComponent do właściwości hero elementu/znacznika
dziecka HeroDetailComponent,
wiązanie zdarzenia (click) (ang. event binding ) wywołuje metodę
selectHero komponentu kiedy użytkownik kliknie wybranego
bohatera.
Architektura Angular 2
23/41
5.2. Dwukierunkowe wiązanie danych
Czwartą formą jest dwukierunkowe wiązanie danych (ang. two-way data
binding ), która łączy wiązanie właściwości i wiązanie zdarzenia w jednej
notacji używając dyrektywy ngModel. Przykład takiej dyrektywy z
komponentu wyświetlającego szczegóły naszego bohatera:
<input [(ngModel)]="hero.name">
W dwukierunkowym wiązaniu danych dane przepływają z właściwości
komponentu do kontrolki HTML jak przy wiązaniu właściwości. Zmiany
dokonywane przez użytkownika przepływają w przeciwnym kierunku do
komponentu, zmieniając wartość odpowiedniej właściwości komponentu na
właśnie wprowadzoną.
Architektura Angular 2
24/41
5.3. Wiązanie danych
Angular przetwarza wszystkie wiązania danych jednorazowo w jednym
cyklu zdarzeń JavaScript, przetwarzając drzewo komponentów aplikacji
algorytmem przeszukiwania w głąb.
Wiązanie danych odgrywa ważna rolę w komunikacji między szablonem i
jego komponentem...
Architektura Angular 2
... jak również między rodzicem i komponentami dzieci.
25/41
6. Dyrektywy
Szablony Angular są dynamiczne.
Podczas generowania z nich widoku, Angular przekształca DOM
zgodnie z instrukcjami podanymi przez dyrektywy.
Dyrektywa jest klasą z metadanymi dyrektywy.
W TypeScript stosujemy dekorator @Directive, który łączy
metadane z klasą.
Architektura Angular 2
26/41
6. Dyrektywy
Jedną z form dyrektywy jest komponent.
Komponent to dyrektywa z dołączonym szablonem.
Dekorator @Component jest w rzeczywistości dekoratorem
@Directive rozszerzonym do obsługi szablonów.
W opisie architektury komponent wyróżniono spośród innych
dyrektyw, ze względu na jego ważność i centralne miejsce w
aplikacjach Angular.
Są dwa rodzaje dyrektyw, które nazywa się strukturalnymi/konstrukcyjnymi
i atrybutowymi. Zwykle pojawiają się wewnątrz elementu jak atrybuty,
czasem jako nazwy, ale częściej jako cel przypisania albo wiązania.
Można oczywiście pisać własne dyrektywy.
Architektura Angular 2
27/41
6. Dyrektywy konstrukcyjne
Dyrektywy konstrukcyjne:
zmieniają ułożenie dodająć, usuwając albo zastępując elementy w
drzewie DOM,
przykłady dwóch dyrektyw konstrukcyjnych:
<div *ngFor="let hero of heroes"></div>
<hero-detail *ngIf="selectedHero"></hero-detail>
*ngFor nakazuje wykonać tyle egzemplarzy znacznika <div> ile jest
w tablicy heroes,
*ngIf uwzględni komponent HeroDetail tylko jeśli wybrany bohater
istnieje.
Architektura Angular 2
28/41
6. Dyrektywy atrybutowe
Dyrektywy atrybutowe:
zmieniają zachowanie albo wygląd istniejącego elementu,
w szablonie wyglądają jak normalne atrybuty HTML,
przykładem może być dyrektywa ngModel, która odpowiada za
dwukierunkowe wiązanie danych:
<input [(ngModel)]="hero.name">
zmienia ona zachowanie elementu (zwykle <input>) ustawiając
wartość wyświetlanej właściwość oraz reagując na zdarzenie
wykonywania zmian.
Angular posiada kilka innych dyrektyw, które:
albo zmieniają strukturę elementów w widoku, np. ngSwitch
albo zmieniają wygląd elementów DOM i komponentów, np. ngStyle
czy ngClass.
Architektura Angular 2
29/41
7. Usługi
Usługa jest ogólną kategorią obejmującą jakąkolwiek wartość, funkcję
czy cechę, która jest potrzebna w naszej aplikacji.
Niemal wszystko może być usługą.
Zwykle jest klasą z wąskim, precyzyjnie określonym celem.
Powinna spełniać jakąś specyficzną funkcję i powinna robić to dobrze.
Przykładowe usługi:
obsługa logowania,
dostęp do danych,
wymiana komunikatów,
kalkulator podatkowy,
konfiguracja aplikacji.
Architektura Angular 2
30/41
7. Usługi
Angular nie zawiera żadnej definicji usługi, nie ma klasy bazowej
ServiceBase...
Jednka usługi są zasadnicze dla działania każdej aplikacji Angular.
Przykład usługi wyświetlającej logi w przeglądarce:
app/logger.service.ts (tylko klasa)
export class Logger
log(msg: any)
{
error(msg: any) {
warn(msg: any) {
}
Architektura Angular 2
{
console.log(msg); }
console.error(msg); }
console.warn(msg); }
31/41
7. Usługi
Usługa HeroService pobiera listę bohaterów i zwraca ją w postaci obietnicy.
app/hero.service.ts (tylko klasa)
export class HeroService {
constructor(
private backend: BackendService,
private logger: Logger) { }
private heroes: Hero[] = [];
getHeroes() {
this.backend.getAll(Hero).then( (heroes: Hero[]) => {
this.logger.log(‘Fetched ${heroes.length} heroes.‘);
this.heroes.push(...heroes); // fill cache
});
return this.heroes;
}
}
Bazuje na dwoch innych usługach: LoggerService oraz BackendService, która
odpowiada za komunikację z serwerem.
Usługi są wszędzie.
Architektura Angular 2
32/41
7. Usługi
Nasze koponenty w dużym stopniu korzystają z usług.
Polegają na usługach w celu spełnienia większości obowiązków.
Komponenty: nie pobierają danych z serwera, nie walidują danych
wejściowych, nie wyświetlają logów bezpośrednio do konsoli.
Wszystkie takie zadania są delegowane do usług.
Zadaniem komponentu jest tylko funkcjonalności użytkownikowi i nic więcej.
Pośredniczy on pomiędzy widokiem a logiką aplikacji (która często
reprezentuje pewną wiedzę o modelu).
Dobry komponent udostępnia właściwości i metody do wiązania danych.
Wszystkie nietrywialne zadania są delegowane do usług.
Architektura Angular 2
33/41
7. Usługi
Angular nie wymusza takich zasad.
Nie zgłosi błędu kiedy stworzymy komponent ”zlew kuchenny”
zawierający 3000 lini kodu.
Angular pomaga nam korzystać z tych zasad ułatwiając dokonywanie
podziału logiki aplikacji na usługi i uczynienie tych usług dostępnymi
dla komponentów dzięki wstrzykiwaniu zależności.
Architektura Angular 2
34/41
8.1. Wstrzykiwanie zależności
Wstrzykiwanie zależności (ang. dependency injection) to mechanizm
dostarczania w pełni funkcjonalnych klas razem ze wszystkimi ich
zależnościami.
Większość zależności to usługi.
Angular używa wstrzykiwania zależności aby dostarczyć komponentom
usług, których potrzebują.
Architektura Angular 2
35/41
8.1. Wstrzykiwanie zależności
Dzięki TypeScript Angular wie jakich usług potrzebuje komponent patrząc
na typ parametrów konstruktora:
app/hero-list.component (konstruktor)
constructor(private service: HeroService) { }
Komponent HeroListComponent potrzebuje usługi HeroService.
Przy tworzeniu komponentu Angular pyta Injector o usługi, których
potrzebuje.
Injector zarządza zasobnikiem instancji różnych usług, które wcześniej
utworzył.
Jeśli potrzebnej usługi nie ma w zasobniku, to jest ona tworzona,
dodawana do zasobnika i dopiero przekazywana do Angulara.
Po uzyskaniu wszystkich usług i przekazaniu ich do Angulara, może
on uruchomić konstruktor komponentu.
To właśnie nazywa się wstrzykiwaniem zależności.
Architektura Angular 2
36/41
8.2. Wstrzykiwanie zależności
Wstrzykiwanie zależności usługi HeroService wygląda mniej więcej tak:
Jeśli Injector nie posiada usługi HeroService to skąd wie jak ją utworzyć?
Wcześniej Injector musi mieć zarejestrowanego dostawcę (ang.
provider) usługi HeroService.
Dostawca to coś co potrafi utworzyć usługę i ją zwrócić.
Zwykle jest to klasa usługi sama w sobie.
Architektura Angular 2
37/41
8.2. Wstrzykiwanie zależności - rejestracja dostawcy
Dostawcę można zarejestrować na każdym poziomie drzewa
komponentów naszej aplikacji.
Robimy to często na najwyższym poziomie przy uruchamianiu,
te same instancje usług są dostępne w całej aplikacji:
app/main.ts (fragment)
bootstrap(AppComponent, [BackendService, HeroService, Logger]);
Można też zarejestrować dostawcę na poziomie wybranego
komponentu:
app/main.ts (fragment)
@Component({
providers:
[HeroService]
})
export class HeroesComponent { ... }
w tym przypadku dostajemy nową instancję usługi dla każdej instancji
komponentu.
Architektura Angular 2
38/41
8.2. Wstrzykiwanie zależności - podsumowanie
wstrzykiwanie zależności jest połączone z Angular i wszędzie używane,
Injector jest głównym mechanizmem:
zarządza zasobnikiem instancji usług, które sam utworzył,
tworzy nowe instancje usług używając dostawcy (provider ),
dostawca jest ”przepisem” na utworzenie usługi,
musimy rejestrować dostawców w ramach Injectora.
Architektura Angular 2
39/41
Pozostałe elementy w Angular 2
Animacje - jest do tego specjalna biblioteka,
Bootstrap - sposoby konfigurowania i uruchamiania aplikacji,
Wykrywanie zmian - sposoby określania stref (ang. zones) ekranu, które
będą aktualizowane przy zmianie danych,
Mechanizm trasowania - komponent Router odpowiedzialny za obsługę
wielu ekranów podobnie jak przeglądarki obsługują wiele adresów URL,
Zdarzenia - drzewo DOM zgłasza zdarzenia, tak samo komponenty i usługi;
Angular ma mechanizmy obsługi zdarzeń,
Formularze - wsparcie dla scenariuszy złożonych danych wejściowych,
walidacja w HTML,
HTTP - wbudowany klient HTTP do pobierania danych, zapisu danych i
wywoływania akcji po stronie serwera,
Wstawki programowe - obsługa dodaktowej funkcjonalności w ramach
cyklu życia komponentu,
Strumienie - przetwarzania wyświetlanych danych (filtry w Angular1),
Testowanie - dostęp do biblioteki do testów jednostkowych.
Architektura Angular 2
40/41
Źródła
https://angular.io/
https://pl.wikipedia.org/wiki/TypeScript
https://www.typescriptlang.org/
http://codeguru.geekclub.pl/baza-wiedzy/
wprowadzenie-do-programowania-w-typescript-wstep,3575
https://developer.mozilla.org/en-US/docs/Web/JavaScript/
Reference/Functions/Arrow_functions
Architektura Angular 2
41/41