Struktura aplikacji
Aplikację Angulara tworzymy w Typescript. Klasy TypeScript mogą reprezentować różne elementy aplikacji - zależnie od użytych dekoratorów:
- Dekorator @NgModule tworzy moduł
- Dekorator @Component tworzy komponent (zawiera m.in. właściwość template opisującą fragment HTML, który ma być renderowany przez przeglądarkę)
- Dekorator @Injectable pozwala na obsługę modułu przez system wstrzykiwania zależności (DI)..
źródło rysunku: Jakob Fain, Anton Moiseev, "Angular 2. Programowanie z TypeScript".
Struktura plików
Aby rozpocząć, utwórzmy aplikację Angulara z pojedynczym komponentem. Aby to zrobić, potrzebujemy następujących plików:
- app/app.component.ts - tutaj definiujemy nasz główny komponent,
- app/app.module.ts - strktura modułu (app) - określa użyte komponenty, potoki i usługi,
- index.html - jest to strona, na której będzie renderowany komponent
- main.ts - główny plik uruchomieniowy - łączący komponent ze stroną, zależy od platformy
app/app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: '<b>Pierwsza aplikacja Angular!</b>'
})
export class AppComponent {
}
- index.html
<body>
<app-root>Loading...</app-root>
</body>
- app/app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component'
@NgModule({
imports: [BrowserModule],
declarations: [AppComponent],
bootstrap: [AppComponent]
})
export class AppModule {
}
- app/main.ts
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.log(err));
Zobacz przykład [001]
Komponenty umieszczamy a podkatalogu src (każdy komponent w odrębnym katalogu). Prócz nich katalog src powinien zawierać pliki:
- index.html - główny plik aplikacji ze znacznikiem wskazującym miejsce renderowania głównego komponentu (zwyczajowo
<app-root></app-root>
. - main.ts - moduł ładowania aplikacji, dostosowany do środowiska na którym ona działa
- polyfills.ts - dodatkowe biblioteki, które zapewniają obsługę użytych funkcji w starszych wersjach przeglądarek WWW.
- styles.css - główny plik z arkuszem styli (może być pusty)
Główny katalog aplikacji poza wspomnianym katalogiem src zawiera:
- tsconfig.json - konfiguracja TypeScript; dodatkowo dla każdego modułu mogą być tworzone pliki dziedziczące ten główny plik - w katalogu src o nazwach tsconfig.[nazwa_modułu].json
- angular.json - konfiguracja Angulara
- package.json - plik zarządzania pakietami NodeJS (npm lub yarn)
Zazwyczaj aplikacje tworzymy przy użyciu programu ng (ng new ... - zobacz rozdział Angular CLI). Nic jednak nie stoi na przeszkodzie, by stworzyć pliki aplikacji w inny sposób. Jedną z takich minimalistycznych propozycji znajdziesz w katalogu (bez plików związanych z testami): https://github.com/tenarjw/ng_intro_by_example/tree/master/min
Proces ładowania (bootstrap) rozpoczyna się od skryptu main.ts , który jest głównym punktem wejścia aplikacji. Deklaruje się w nim moduł główny aplikacji - nazywany zazwyczaj AppModule
. W tym module dopiero jest skonfigurowany komponen ( AppComponent
), który powinien wyrenderować aplikację (z selektorem app-root
). Dlatego umieszcza się jego nazwę we własności bootstrap
wspomnianego wyżej głównego modułu. Jest on renderowany na każdym napotkanym elemencie HTMLapp-root
. Dlatego w pliku index.html umieszczamy element app-root
.
Plik _ app/main.ts _zawiera użycie funkcji platformBrowserDynamic().BootstrapModule(AppModule)
do uruchomienia procesu ładowania.
Dlaczego Angular uruchamia się w ten sposób? Ponieważ Angular nie jest strukturą opartą wyłącznie w internecie, możemy napisać komponenty, które będą działać w NativeScript lub Cordova, lub dowolnym innym środowisku, które może obsługiwać aplikacje Angular. Wtedy w procesie ładowania możemy zaimportować platformę, z której chcielibyśmy korzystać, w zależności od środowiska, w którym działamy. W naszym przykładzie, ponieważ tworzymy aplikację Angular w przeglądarce, użyliśmy procesu ładowania znajdującego się w @angle/platform-browser-dynamic
.
Pozostawienie procesu ładowania w oddzielnym pliku _ main.ts _jest zdecydowanie bardzo dobrym pomysłem. Ułatwia to testowanie (ponieważ komponenty są odizolowane od wywołania bootstrap
), łatwiej je ponownie wykorzystać. Zapewnia to lepszą organizację i strukturę naszej aplikacji.
W większości przykładów dołączonych do niniejszego podręcznika, zawarto jedynie pliki modułów. Można je umieścić w dowolnej aplikacji testowej (np. utworzonej komendą ng new).
Usługi
Pojęcie "usługi" jest dość ogólne - określa się nim zazwyczaj klasą o wąskim, dobrze zdefiniowanym celu (robi coś konkretnego). Niemniej rozróżnienie usług i komponentów jest dla Angulara ważne (https://angular.io/guide/architecture-services\ - zwłaszcza gdy stosujemy "wstrzykiwanie zależności" (zostanie to omówione w odrębnym rozdziale).
Ponieważ proces ładowania początkowego uwzględnia również wspomniany system zależności - poza zadeklarowaniem wykorzystywanych komponentów (właściwość declarations) musimy wskazać "dostawców usług" (własność providers). Poniższy przykład modułu pokazuje rejestrowanie jako usługi komponentu o nazwie GreeterService
.
app/app.module.ts
import { Component, OnInit } from '@angular/core';
import { GreeterService } from './greeter.service';
@Component({
selector: 'app-root',
template: '<b>{{greeting}}</b>'
})
export class AppComponent implements OnInit {
public greeting ='';
constructor(private greeterService: GreeterService) { }
ngOnInit() {
this.greeting = this.greeterService.getMessage();
}
}
Zobacz przykład [002]