Wie schon bei den Libraries erwähnt, wirken Framewors im ersten Moment
ähnlich zu einer Library. Frameworks sind aber sozusagen eine
Struktur/Grundgerüst mit vorgefertigten verschiedenen Materialien, mit
dem du dir dein Projekt selbst einfach und schnell aufbauen kannst.
Zusätzlich gibt es noch einen weiteren entscheidenden Unterschied, und
zwar die sogenannte "inversion of control" (Steuerungsumkehr).
Wird eine Library verwendet ist man selbst für den Ablauf der
Anwendung verantwortlich. Das heißt man legt selbst fest, wann und wo
die Library aufgerufen werden soll.
Bei einem Framework ist dies selbst für den Ablauf verantwortlich. Es
gibt zwar Platz um eigenen Code einzubringen, entscheidet aber selbst
wann dieser aufgerufen wird.
Hier ist ein Beispiel mit jQuery (einer Bibliothek) und Vue.js (einem
Framework):
Stell dir vor, wir möchten eine Fehlermeldung anzeigen, wenn ein
Fehler vorliegt. In unserem Beispiel klicken wir auf eine Schaltfläche
und tun so, als ob ein Fehler auftritt.
Mit jQuery:
Hier verwenden wir jQuery. Wir sagen dem Programm genau wo wir es
brauchen. Das heißt nicht, dass für jQuery-Funktionen bestimmte
Eingaben nicht erforderlich sind, wenn wir sie aufrufen, aber jQuery
selbst ist eine Bibliothek dieser Funktionen. Wir sind verantwortlich.
Mit Vue.js:
freecodecamp.org
Bei Vue.js müssen wir sozusagen die Lücken füllen. Der Vue-Konstruktor
ist ein Objekt mit bestimmten Eigenschaften. Es sagt uns was es
braucht und Vue.js entscheidet dann wann es es braucht. Vue kehrt die
Steuerung des Programms um. Wir stecken unseren Code rein und Vue
übernimmt die Verantwortung.
Frameworks für individuelle Problemstellungen
Frameworks bieten einen Basis-Bausteinkasten und nehmen somit Einfluss
auf die Design-Struktur unseres Programms. Es gibt für viele
Einsatzmöglichkeiten passende Framework-Typen:
- Web-Frameworks:
-
mit Zuschnitt auf die Entwicklung und Programmierung dynamischer Web
Sites und Web Applikationen
- Application Frameworks:
-
als Programmier-Gerüst für Anwendungen mit spezifischen Strukturen
und Funktionen
- Komponenten-Frameworks:
-
mit speziellem Umgebungsrahmen für die Programmierung und finale
Einbindung von Programm-Paketen
- Coordination Frameworks:
-
mit der Möglichkeit der Einrichtung von Geräte-Interaktionen, das
heißt einer Abfolge zu steuernder Ablaufschritte
- Domain Frameworks:
- als Programmier-Rahmen für definierte Problembereiche
- Class Frameworks:
-
mit der Aufgabenstellung einer Zusammenfassung von „Klassen“ und
„Methoden“, im Sinne einer optimalen Unterstützung des
Programmierers bei der Implementierung spezifischer Anwendungen
- Test Frameworks:
-
zum Testen entwickelter Software Programme. Als klassische Beispiele
sind „Selenium oder Cypress“ für den Test von Web Applikationen und
„JUnit“ für den Test von Modulen zu nennen
- Wofür werden Js-Frameworks verwendet?
-
- Webseiten erstellen
- Front-End App Entwicklung
- Back-End App-Entwicklung
- Hybride App-Entwicklung
- Ecommerce Anwendungen
- Modulare Skripte bauen, zum Beispiel Node.js
- DOM manuell aktualisieren
-
Automatisieren von sich wiederholenden Aufgaben mit Templates
und 2-Wege-Bindung
- Videospiele entwickeln
- Bildkarussells erstellen
- Codes testen und debuggen
- Module bündeln
Auf dieser Seite findest du viele verschiedene
Frameworks.
Angular:
Angular ist ein Anwendungsdesign-Framework und eine
Entwicklungsplattform zum Erstellen effizienter und anspruchsvoller
Single-Page-Apps. Zudem wird es nicht mit JavaScript, sondern
Typescript aufgebaut.
- Was kann Angular?
-
-
Es ist ein komponentenbasiertes Framework zum Erstellen
skalierbarer Webanwendungen
-
Es ist eine sammlung gut intergierter Bibliotheken, die viele
Funktionen abdecken. Wie bspw. Routing, Formularverwaltung,
Client-Server-Kommunikation usw.
-
Es hat eine Reihe von Entwicklertools, mit denen der Code
einfacher entwickelt, erstellt, getestet und aktualisiert werden
kann
-
Hier sind Beispiele und Insights aus dem
Tour of Heroes Tutorial von Angular:
Kapitel 1
Im ersten Kapitel geht es um die Grundstruktur des Helden-Editors:
-
Mit der CLI (Command Line Interface) wurde als erstes die
HeroesComponent angelegt.
-
In der app.component.html wurde die HeroesComponent eingetragen
um diese anzeigen zu lassen. Die AppComponent ist sozusagen die
Anzeige für alle Componenten. Wenn hier eine Component
eingetragen wird kann über den CLI Befehl "ng serve" diese auf
dem lokalen Server angezeigt werden.
-
Durch die UpperCasePipe im <h2> in der
heroes.component.html werden die Heronamen immer in
Großbuchstaben geschrieben.
-
Durch ngModel wurde eine Verbidnung von hero.name mit der
Textbox hergestellt. ([(ngModel)] ist die bidirektionale
Datenbindungssyntax von Angular.) Das heißt hier fließen die
Daten in beide Richtungen, sodass die hero.name Eigenschaft an
die Textbox und wieder zurück gegeben werden kann.
-
Durch den Import von "FormsModule" im AppModule kann die ngModel
Direktive aufgerufen werden. Das heißt hierdurch wird das
App-Modul erstellt und dies enthält dann alle Abhängigkeiten und
Komponenten. Durch laden des Moduls wird der AppComponent
gestartet.
Kapitel 2
Im zweiten Kapitel geht es um die Liste der Heroes die ausgewählt
werden können:
-
Durch eine Mock-Datei "mock-heroes.ts" wurde eine Liste an
Heroes generiert.
-
Damit die Nutzer:innen einen Hero auswählen kann wird diese
Liste angezeigt. Hierfür wurde "*ngFor" verwendet. Dies ist eine
"Repeater-Direktive" von Angular ähnlich wie eine For-Schleife
wiederholt er in hier das Host-Element für jedes Element in der
Liste. <li> ist das Host-Element. Die Klasse heroes
enthält die Liste der "Helden" aus der HeroesComponent Klasse.
Das aktuelle Heldenobjekt ist in "hero" enthalten und wird durch
das *ngFor für jede Iteration in der Liste angezeigt.
-
(click)="onSelect(hero)" ist ein Besipiel für die event binding
Syntax von Agular. Hier wird ein Klick-Event auf einen Hero
vorgenommen. Das Event wird in der heroes.component.ts als
Methode definiert (event handler). Zunächst soll kein Hero
ausgewählt sein, bis der/die Nutzer:in auf einen Hero klickt.
-
Mit "*ngIf" in der heroes.component.html wird nun definiert,
wann ein Hero ausgewählt (selectedHero) ist und wann nicht.
Ebenfalls wie bei *ngFor ist *ngIf ähnlich der If-Bedingung.
Sprich wenn kein Hero ausgewählt ist zeige keine Details an, ist
ein Hero ausgewählt zeige die Details des Hero's.
-
Als letztes wurden Klassenanbindungen (class binding) zu den
jeweiligen Elementen die eine andere Klasse haben sollen wenn
sie bspw. ausgewählt sind, hinzugefügt. Im heroes.componen.css
wurden hierfür Styles für die verschiedenen States der Hero's
angelegt.
Kapitel 3
Im dritten Kapitel geht es darum verschiedene Teile einer Componente
auszulagern um für jede Funktion/Darstellung einzelne
Feature-Componenten zu haben:
-
Es wurde eine neue Componente erstellt mit dem Namen
"hero-detail.component". Diese dient der Anzeige der
Herodetails, hier wurde also lediglich der Detailpart aus der
hero.component in eine extra Komponente ausgelagert.
-
[hero]="selectedHero" ist ein Angular "property binding", das
heißt es wurde der HeroesComponent die Kontolle über die
untergeordnete Hero-DetailComponent gegeben. Es sollte somit
also jedesmal wenn auf einen Hero geklickt wird das property
binding aktualisiert und die Details zu dem Hero angezeigt
werden.
-
Damit die Hero-DetailComponent weiß welcher Hero gemeint ist
wird "@Input() hero?: Hero;" in die hero-detail.component.ts
hinzugefügt. Somit werden Daten zwischen den Eltern- und
Kind-Komponenten geteilt. --> Über @Output kann die
Kind-Komponente Daten an die Eltern-Komponente schicken.
Kapitel 4
Im vierten Kapitel geht es darum verschiedene Services bereit zu
stellen. Diese Services können alle Anwendungsklassen benutzen um
Helden zu erhalten. Anstatt diesen Dienst über das Stichwort "new"
zu erstellen, wird dies über die Angular "dependency injection" im
Konstruktor der HeroesComponent eingefügt:
-
Zunächst wird ein Angular Service erstellt mit dem Namen
"hero.service.ts". Durch hinzufügen der heroService Parameter im
Konstruktor der HeroesComponent mit "constructor(private
heroService: HeroService) {}" werden diese injiziert. Wenn
Agular jetzt eine HeroesComponent erstellt, setzt das Dependency
Injection system die heroService Parameter als Instanz des
HeroServices.
@Injectable
Injectables markieren die Klasse als "Teilnehmer" des Dependency
Injection systems. Das heißt der Injektor erstellt Dependencies
(Abhängigkeiten) und verwaltet einen Container mit dependency
instances die er nach Möglichkeit wiederverwenden kann. Ein
provider ist ein Objekt, das einem Injektor mitteilt, wie eine
dependency abgerufen oder erstellt wird. Damit in Angular die
Dienste aufgerufen werden können müssen diese im Konstruktor der
Komponente aufgerufen werden.
-
Der Konstuktor sollte so wenig wie möglich machen, deshalb wird
mit getHeroes() im ngOnInit Lifecycle-Hook aufgerufen. Angular
soll dann, nach dem er eine Instanz für die HeroesComponent
konstruiert hat, ngOnInit() aufrufen.
ngOnInit() {
this.getHeroes();
}
-
Da wir gerade eine Mock-Datei mit "Scheinhelden" haben lassen
sich diese synchron abrufen. Dies soll jedoch in Zukunft
asynchron ablaufen, wenn bspw. die Daten über eine Remote-Server
abgerufen werden. Somit benötigen wir einen asynchrone Signatur
umd diese in Zukunft asynchron abgrufen zu können. Die
getHeroes() Methode wird deshalb zu einer Beobachtbaren Methode
gemacht:
import { Observable, of } from 'rxjs';
getHeroes(): Observable<Hero[]> {
const heroes = of(HEROES);
return heroes;
}
of(HEROES) gibt nun ein Observable<Hero[]> zurück, der
einen einzelnen Wert ausgibt, nämlich das Array von
Scheinhelden. Die HeroService.getHeroes Methode hat bisher
Hero[] zurückgegeben. Nun gibt sie Observable<Hero[]>
zurück. Das muss so auch noch in der HeroesComponent angepasst
werden. Deshalb wird die getHeroes() mit einem subscribe
ergänzt:
getHeroes(): void {
this.heroService.getHeroes()
.subscribe(heroes => this.heroes = heroes);
}
Mit dieser Version der getHeroes() Methode wird auf das
Observable gewartet, welches den Array jetzt oder in einigen
Minuten ausgibt. Mit der subscribe() Methode wird nun das
ausgegebene Array an den Callback übergeben der die heroes
Eigenschaft der Komponente festlegt.
Observables
Observables (dt. beobachtbar)
Ein Observer - zu Deutsch Beobachter - behält etwas im Auge und
reagiert auf mögliche Änderungen. Möchte ein anderer
Anwendungsteil vom Observer über die Änderungen am Observable
informiert werden, kann er sich an diesem dazu an- (subscribe)
und auch wieder abmelden (unsubscribe). Ein Observable kann
dabei abstrakt einfach als Daten-Stream betrachtet werden.
Dadurch sind diese auch flexibel einsetzbar und es können
beispielsweise mehrere Observables verknüpft oder
zusammengefasst werden. Das Prinzip ähnelt stark dem
Observer-Pattern und nennt sich Reactive Programming. Angular
nutzt als Basis dazu die Observables der ReactiveX Architektur
(kurz: RxJS).
RxJS
RxJS ist eine Bibliothek für die reaktive Programmierung mit
Observables, um die Erstellung von asynchronem oder
callback-basiertem Code zu vereinfachen.
-
Services sind eine Möglichkeit, Informationen zwischen Klassen
auszutauschen, die sich nicht kennen. Zusätzlich wurde noch der
"message.service.ts" erstellt. Der MessageService injiziert an
zwei Stellen. Inject in HeroService, der den Dienst zum Senden
einer Nachricht verwendet. Inject in MessagesComponent, die
diese Nachricht anzeigt und auch die ID anzeigt, wenn der
Benutzer auf einen Helden klickt.
-
Damit die Message angezeigt werden kann wurde eine
MessageComponent erstellt. Diese gibt aus welcher Hero
angeklickt wurde und welche ID er hat. Diese können über den
"clear messages" Button gelöscht werden.
Kapitel 5
Im fünften Kapitel geht es darum zwischen zwei Ansichten über das
Angular Routing-Module zu wechseln. Es geht also um eine erweiterte
Navigation innerhalb der Seite und die verschiedenen Abhängigkeiten
dieser zueinander:
-
Der/Die Nutzer:in kann dann wie folgt in der Anwendung
navigieren:
-
Wie auf der Grafik zu sehen wurde eine weitere Komponente
erstellt, das Dashboard. Auf dem Dashboard werden "Top Heroes"
angezeigt. Genau wie in der HeroesComponent sollen hier die
Details der Heroes angezeigt werden, wenn der/die Nutzer:in auf
einen "Top Hero" klickt.
-
Routing
Das Routing in Angular hilft uns, von einer Ansicht zur anderen
zu navigieren, während Benutzer:innen Aufgaben in Web-Apps
ausführen. Der Angular-Router ist ein Kernstück der
Angular-Plattform. Angular bietet eine vollständige
Routing-Bibliothek mit der Möglichkeit, mehrere Router-Ausgänge,
verschiedene Pfadanpassungsstrategien, einfachen Zugriff auf
Routenparameter und route guards (Routenwächter) zum Schutz vor
unbefugtem Zugriff auf Komponenten.
Ein Router funktioniert wie folgt:
-
er liest die Browser-URL, zu der der/die Benutzer:in
navigieren möchte
-
er wendet eine URL-Umleitung an (sofern eine definiert ist)
-
er findet heraus, welcher Router-Zustand der URL entspricht
-
er führt die Guards aus, die im Routerstatus definiert sind
-
er löst die erforderlichen Daten für den Routerstatus auf
-
Im Tutorial wird ein neues Routing-Module erstellt, um im
späteren Verlauf zwischen dem Dashboard (kommt noch) und der
Heroes Seite zu wechseln. Das Module wird app-routing.module.ts
genannt. Es gibt zwei typische Elemente:
path: eine Zeichenfolge, die mit der URL in der Adressleiste des
Browsers übereinstimmt.
component: die Komponente, die der Router erstellen soll, wenn
er zu dieser Route navigiert.
const routes: Routes = [
{ path: 'heroes', component: HeroesComponent }
];
In der app.component.html wird die <app-heroes> durch
<router-outlet> ausgetauscht. Zusätzlich wird ein
routerLink hinzugefügt.
<a routerLink="/dashboard">Dashboard</a>
<a routerLink="/heroes">Heroes</a>
-
Damit die verschiedenen Komponenten untereinander verknüpft
sidn, werden mehrere routerLinks gesetzt. Dieser verknüpft auch
die Detailansicht sowohl mit dem Dashboard als auch mit der
HeroesComponent.