Angular 6 Tutorial: Neue Features mit neuer Power

Veröffentlicht: 2022-03-11

Winkel 6 ist da! Die herausragendsten Änderungen betreffen die CLI und wie Dienste injiziert werden. Wenn Sie Ihre allererste Angular 6-App – oder Angular/Firebase-App – schreiben möchten, gehen wir in diesem Tutorial die grundlegenden Schritte der Ersteinrichtung durch und erstellen eine kleine Tagebuch-App.

Eckig 6: Die Grundlagen

Wenn Sie Angular noch nie zuvor verwendet haben, lassen Sie mich Ihnen kurz beschreiben, wie es funktioniert.

Angular ist ein JavaScript-Framework, das entwickelt wurde, um die Erstellung von Single-Page-Anwendungen (SPAs) für Desktop- und Mobilgeräte zu unterstützen.

Das Framework umfasst eine vollständige Suite von Anweisungen und Modulen, mit denen Sie einige der häufigsten Szenarien für eine Web-App wie Navigation, Autorisierung, Formulare und Berichterstellung einfach implementieren können. Es enthält auch alle erforderlichen Pakete, um Tests mit dem Jasmine-Framework hinzuzufügen und sie mit den Karma- oder Protractor-Testläufern auszuführen.

Die Angular-Architektur basiert auf Komponenten, Vorlagen, Anweisungen und Diensten. Es bietet einen integrierten Abhängigkeitsinjektionsmechanismus für Ihre Dienste sowie eine bidirektionale Datenbindung, um Ihre Ansichten mit Ihrem Komponentencode zu verbinden.

Angular verwendet TypeScript, eine typisierte Obermenge von JS, und wird einige Dinge einfacher machen, insbesondere wenn Sie einen typisierten Sprachhintergrund haben.

Winkel 6: Neue Funktionen

Eine kurze Zusammenfassung der neuen Funktionen in Angular 6:

  • Eine Richtlinie zum Synchronisieren von Hauptversionsnummern für die Framework-Pakete ( @angular/core , @angular/common , @angular/compiler usw.), CLI, Material und CDK. Dies hilft, die Querkompatibilität zukünftig klarer zu machen: Auf einen schnellen Blick auf die Versionsnummer können Sie erkennen, ob Schlüsselpakete miteinander kompatibel sind.
  • Neue ng -CLI-Befehle:
    • ng update , um Paketversionen intelligent zu aktualisieren, Abhängigkeitsversionen zu aktualisieren und sie synchron zu halten. (Wenn Sie zB ng update @angular/core ausführen, werden alle Frameworks sowie RxJS aktualisiert.) Es werden auch Schemata ausgeführt, wenn das Paket diese enthält. (Wenn eine neuere Version Breaking Changes enthält, die Codeänderungen erfordern, aktualisiert der Schaltplan Ihren Code für Sie.)
    • ng add , um neue Pakete hinzuzufügen (und ggf. Skripte auszuführen)
  • Dienste verweisen jetzt auf die Module, die sie bereitstellen, anstatt dass Module auf Dienste verweisen, wie sie es früher hatten.

Als Beispiel dafür, was diese letzte Änderung bedeutet, wo Ihr Code früher so aussah:

 @NgModule({ // ... providers: [MyService] })

…mit dieser speziellen Änderung in Angular 6 wird es so aussehen:

 @Injectabe({ providedIn: 'root', })

Diese werden als baumstrukturierbare Anbieter bezeichnet und ermöglichen dem Compiler, nicht referenzierte Dienste zu entfernen, was zu kleineren Bündeln führt.

Winkel 6 CLI

Die ng -Befehlszeilenschnittstelle ist ein sehr wichtiger Teil von Angular und ermöglicht es Ihnen, sich beim Codieren Ihrer App schneller zu bewegen.

Mit der CLI können Sie Ihre anfängliche App-Einrichtung sehr einfach aufbauen, neue Komponenten, Anweisungen usw. generieren und Ihre App in Ihrer lokalen Umgebung erstellen und ausführen.

Erstellen eines Angular 6-Projekts

Okay, genug geredet. Machen wir uns die Hände schmutzig und fangen an zu programmieren.

Zu Beginn müssen Node.js und npm auf Ihrem Computer installiert sein.

Lassen Sie uns nun fortfahren und die CLI installieren:

 npm install -g @angular/cli

Dadurch wird der CLI-Befehl ng aufgrund des Schalters -g global installiert.

Sobald wir das haben, können wir mit ng new das anfängliche Gerüst für unsere App erhalten:

 ng new my-memories --style=scss

Dadurch wird ein Ordner my-memories erstellt, alle erforderlichen Dateien erstellt, um Ihre Ersteinrichtung startbereit zu machen, und alle erforderlichen Pakete installiert. Der Schalter --style=scss ist optional und richtet den Compiler so ein, dass er SCSS-Dateien in CSS kompiliert, was wir später benötigen.

Sobald die Installation abgeschlossen ist, können Sie cd my-memories und ng serve ausführen. Dadurch werden der Erstellungsprozess und ein lokaler Webserver gestartet, der Ihre App unter http://localhost:4200 .

Eine Angular 6 App unmittelbar nach dem Gerüstbau

Was hinter den Kulissen passiert, ist, dass die CLI alle .ts (TypeScript-Dateien) in Vanilla JS transpiliert, alle erforderlichen Abhängigkeiten aus dem node_modules und das Ergebnis in einer Reihe von Dateien ausgibt, die über einen lokalen Webserver bereitgestellt werden das läuft auf Port 4200.

Projektdateien

Wenn Sie mit der Projektordnerstruktur von Angular nicht vertraut sind, ist das Wichtigste, was Sie wissen müssen, dass der gesamte Code, der sich auf die App bezieht, im src -Ordner abgelegt wird. Normalerweise erstellen Sie alle Ihre Module und Anweisungen in diesem Ordner entsprechend Ihrer App-Architektur (z. B. Benutzer, Warenkorb, Produkt).

Die Projektordnerstruktur von Angular 6

Ersteinrichtung

Okay, bisher haben wir die Ersteinrichtung für unsere App. Beginnen wir mit einigen Änderungen.

Bevor wir beginnen, lassen Sie uns ein wenig in den src -Ordner eintauchen. Die Startseite ist index.html :

 <!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>MyMemories</title> <base href="/"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" type="image/x-icon" href="favicon.ico"> </head> <body> <app-root></app-root> </body> </html>

Hier sehen wir etwas grundlegendes HTML und das <app-root> -Tag. Dies ist eine Angular-Komponente, und Angular 6 fügt unseren Komponentencode ein.

Wir finden die Datei app/app.component.ts “, die den Selektor „ app-root “ enthält, der mit dem übereinstimmt, was in der Datei „ index.html “ steht.

Die Komponente ist eine dekorierte TypeScript-Klasse und enthält in diesem Fall die title . Der @Component Dekorator weist Angular an, das Komponentenverhalten in die Klasse aufzunehmen. Zusätzlich zum Selektor gibt er an, welche HTML-Datei gerendert und welche Stylesheets verwendet werden sollen.

 import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'] }) export class AppComponent { title = 'app'; }

Wenn wir uns app.component.html ansehen, sehen wir die Interpolationsbindung {{title}} . Hier findet die gesamte magische Bindung statt, und Angular rendert den Wert der Klassentiteleigenschaft und aktualisiert ihn jedes Mal, wenn er sich ändert.

 <!--The content below is only a placeholder and can be replaced.--> <div> <h1> Welcome to {{ title }}! </h1> <img width="300" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg=="> </div> <h2>Here are some links to help you start: </h2> <ul> <li> <h2><a target="_blank" rel="noopener" href="https://angular.io/tutorial">Tour of Heroes</a></h2> </li> <li> <h2><a target="_blank" rel="noopener" href="https://github.com/angular/angular-cli/wiki">CLI Documentation</a></h2> </li> <li> <h2><a target="_blank" rel="noopener" href="https://blog.angular.io/">Angular blog</a></h2> </li> </ul>

Lassen Sie uns fortfahren und den title der Klasse auf 'My Memories!' .

 ... export class AppComponent { title = 'My Memories!'; } ...

Der Compiler verarbeitet unsere Änderung und der Browser wird aktualisiert, um unseren aktualisierten Titel anzuzeigen.

Das bedeutet, ng serve von Angular 6 auf unsere Dateiänderungen achtet und jedes Mal rendert, wenn eine Änderung in eine Datei eingeführt wird.

Um die Programmierung benutzerfreundlicher zu gestalten und eine vollständige Seitenaktualisierung bei jeder Änderung zu vermeiden, können wir das Webpack Hot Module Replacement (HMR) nutzen, das nur den geänderten Teil von JS/CSS aktualisiert, anstatt eine vollständige Aktualisierung zu erzeugen Zeigen Sie Ihre Änderungen.

HMR konfigurieren

Zuerst müssen wir die Umgebung einrichten.

Erstellen Sie eine Datei src/environments/environment.hmr.ts mit folgendem Inhalt:

 export const environment = { production: false, hmr: true };

Aktualisieren Sie src/environments/environment.prod.ts und fügen Sie der Umgebung das hmr: false hinzu:

 export const environment = { production: true, hmr: false };

Dann aktualisiere src/environments/environment.ts und füge auch dort das hmr: false Flag zur Umgebung hinzu:

 export const environment = { production: false, hmr: false };

Aktualisieren Sie als Nächstes in der Datei angular.json diesen Teil:

 "projects": { "my-memories": { // ... "architect": { "build": { // ... "configurations": { "hmr":{ "fileReplacements":[ { "replace": "src/environments/environment.ts", "with": "src/environments/environment.hmr.ts" } ] }, // ...

Und unter projectsmy-memoriesarchitectserveconfigurations :

 "projects": { "my-memories": { "architect": { // ... "serve": { // ... "configurations": { "hmr": { "browserTarget": "my-memories:build:hmr" }, // ...

Aktualisieren Sie nun tsconfig.app.json , um die erforderlichen types (gut, Typ) einzuschließen, indem Sie dies unter compilerOptions hinzufügen:

 "compilerOptions": { // ... "types": [ "node" ]

Als Nächstes installieren wir das Modul @angularclass/hmr als Entwicklungsabhängigkeit:

 npm install --save-dev @angularclass/hmr

Konfigurieren Sie es dann, indem Sie eine Datei src/hmr.ts :

 import { NgModuleRef, ApplicationRef } from '@angular/core'; import { createNewHosts } from '@angularclass/hmr'; export const hmrBootstrap = (module: any, bootstrap: () => Promise<NgModuleRef<any>>) => { let ngModule: NgModuleRef<any>; module.hot.accept(); bootstrap().then(mod => ngModule = mod); module.hot.dispose(() => { const appRef: ApplicationRef = ngModule.injector.get(ApplicationRef); const elements = appRef.components.map(c => c.location.nativeElement); const makeVisible = createNewHosts(elements); ngModule.destroy(); makeVisible(); }); };

Aktualisieren Sie als Nächstes src/main.ts , um die obige Funktion zu verwenden:

 import { enableProdMode } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app/app.module'; import { environment } from './environments/environment'; import { hmrBootstrap } from './hmr'; if (environment.production) { enableProdMode(); } const bootstrap = () => platformBrowserDynamic().bootstrapModule(AppModule); if (environment.hmr) { if (module[ 'hot' ]) { hmrBootstrap(module, bootstrap); } else { console.error('HMR is not enabled for webpack-dev-server!'); console.log('Are you using the --hmr flag for ng serve?'); } } else { bootstrap().catch(err => console.log(err)); }

Was wir hier tun, ist, den Bootstrap-Aufruf zu einer anonymen Funktion zu machen und als Nächstes zu fragen, ob das Flag „ environment.hmr “ wahr ist. Wenn dies der Fall ist, rufen wir die zuvor definierte Funktion von hmr.ts , die den Hot-Modulaustausch ermöglichte; Andernfalls booten wir es wie gewohnt.

Wenn wir jetzt ng serve --hmr --configuration=hmr , rufen wir die hmr Konfiguration auf, und wenn wir Änderungen an Dateien vornehmen, erhalten wir Updates ohne vollständige Aktualisierung. Das erste --hmr ist für webpack und --configuration=hmr ist für Angular, um die hmr Umgebung zu verwenden.

Progressive Web-App (PWA)

Um Angular 6 PWA-Unterstützung hinzuzufügen und das Offline-Laden für die App zu ermöglichen, können wir einen der neuen CLI-Befehle verwenden, ng add :

 ng add @angular/[email protected]

Beachten Sie, dass ich die Version hinzufüge, da die neueste Version, als ich dieses Tutorial schrieb, einen Fehler auslöste. (Sie können es ohne es versuchen und prüfen, ob es für Sie funktioniert, indem Sie einfach ng add @angular/pwa .)

Okay, nachdem wir den Befehl ausgeführt haben, werden wir viele Änderungen an unserem Projekt sehen. Die wichtigsten Änderungen sind, dass es hinzugefügt wurde:

  • Ein Verweis auf manifest.json in der Asset-Datei „ angular.json “, sodass sie in der Build-Ausgabe enthalten ist, sowie "serviceWorker": true in Produktions-Builds
  • Die Datei ngsw-config.json mit der Ersteinrichtung, um alle Dateien zwischenzuspeichern, die für die Ausführung der App erforderlich sind
  • Ein manifest.json -Meta-Tag in der index.html -Datei
  • Die manifest.json -Datei selbst mit einer grundlegenden Konfiguration für die App
  • Laden des Dienst-Workers im App-Modul ServiceWorkerModule.register('/ngsw-worker.js', { enabled: environment.production }) (beachten Sie, dass der Dienst-Worker nur in Produktionsumgebungen aktiviert wird)

Das bedeutet jetzt, dass die Dateien heruntergeladen werden, wenn der Benutzer zum ersten Mal auf die URL zugreift. Wenn der Benutzer danach versucht, ohne Netzwerkdienst auf die URL zuzugreifen, funktioniert die App weiterhin, indem sie diese zwischengespeicherten Dateien abruft.

Hinzufügen der Material Angular 6 UI-Bibliothek

Bisher haben wir die Ersteinrichtung und können mit der Erstellung unserer App beginnen. Um bereits gebaute Komponenten zu nutzen, können wir die Angular 6-Version von Material verwenden.

Um das material in unserer App zu installieren, verwenden wir wieder ng add :

 ng add @angular/material

Nachdem wir das ausgeführt haben, werden einige neue Pakete hinzugefügt und einige grundlegende Stilkonfigurationen:

  • index.html enthält die Roboto-Schriftart und Materialsymbole
  • BrowserAnimationsModule wird unserem AppModule hinzugefügt
  • angular.json hat das Indigo-Pink-Design bereits für uns enthalten

Zeigt Ihre Wahl eines vorgefertigten Angular 6-Designs an

Sie müssen ng serve neu starten, um das Design aufzunehmen, oder Sie können ein anderes vorgefertigtes Design auswählen.

Siehe auch: Erstellen Sie hochmoderne Web-Apps mit Angular Material

Grundlayout

Um das anfängliche Sidenav-Layout zu erhalten, verwenden wir die Schemata, die mit Material geliefert werden. Aber es ist in Ordnung, wenn Sie ein anderes Layout verwenden möchten.

(Kurz gesagt, mit Schaltplänen können Sie Transformationen auf ein Projekt anwenden: Sie können Dateien nach Bedarf erstellen, ändern oder löschen. In diesem Fall wird ein Seitennavigationslayout für unsere App erstellt.)

 ng generate @angular/material:material-nav --name=my-nav

Dadurch wird eine sidenav-Komponente mit der minimalen Einrichtung erstellt, die startbereit ist. Ist das nicht toll?

Es hat auch alle notwendigen Module in unsere app.module.ts .

Eine neu erstellte "my-nav" Angular 6-Komponente

Da wir SCSS verwenden, müssen wir die Datei my-nav.component.scss my-nav.component.css my-nav.component.scss umbenennen und in my-nav.component.ts die entsprechenden Referenz- styleUrls aktualisieren, um den neuen Namen zu verwenden.

Um nun die neue Komponente zu nutzen, gehen wir zu app.component.html und entfernen den gesamten ursprünglichen Code, sodass nur Folgendes übrig bleibt:

 <app-my-nav></app-my-nav>

Wenn wir zum Browser zurückkehren, sehen wir Folgendes:

Ein Vier-Fenster-Layout mit Menü in der oberen linken Ecke, daneben meine Erinnerungen und drei nummerierte Links unter Menü; der vierte Bereich ist leer

Lassen Sie uns die Links aktualisieren, um nur die beiden gewünschten Optionen zu haben.

Lassen Sie uns zunächst zwei neue Komponenten erstellen:

 ng gc AddMemory ng generate @angular/material:material-table --name=view-memories

(Das zweite ist ein Materialschema, das zum Erstellen einer Tabelle verwendet wird.)

Als Nächstes aktualisieren wir auf my-nav , um die Links einzurichten, und fügen das <router-outlet> ein, um unsere Inhaltskomponenten anzuzeigen:

 <mat-sidenav-container class="sidenav-container"> <mat-sidenav #drawer class="sidenav" fixedInViewport="true" [attr.role]="(isHandset$ | async) ? 'dialog' : 'navigation'" [mode]="(isHandset$ | async) ? 'over' : 'side'" [opened]="!(isHandset$ | async)"> <mat-toolbar color="primary">Menu</mat-toolbar> <mat-nav-list> <a mat-list-item [routerLink]="['/add-memory']">Add Memory</a> <a mat-list-item [routerLink]="['/view-memories']">View My Memories</a> </mat-nav-list> </mat-sidenav> <mat-sidenav-content> <mat-toolbar color="primary"> <button type="button" aria-label="Toggle sidenav" mat-icon-button (click)="drawer.toggle()" *ngIf="isHandset$ | async"> <mat-icon aria-label="Side nav toggle icon">menu</mat-icon> </button> <span>my-memories</span> </mat-toolbar> <router-outlet></router-outlet> </mat-sidenav-content> </mat-sidenav-container>

Außerdem müssen wir in app.component.html aktualisieren, damit nur das Haupt- <router-outlet> vorhanden ist (dh <my-nav> entfernen):

 <router-outlet></router-outlet>

Als Nächstes fügen wir im AppModule die Routen ein:

 import { RouterModule, Routes } from '@angular/router'; // ... imports: [ // ... RouterModule.forRoot([ { path: '', component: MyNavComponent, children: [ { path: 'add-memory', component: AddMemoryComponent }, { path: 'view-memories', component: ViewMemoriesComponent } ] }, ]), ]

Beachten Sie, dass wir MyNavComponent als übergeordnetes Element und die beiden von uns erstellten Komponenten als untergeordnete Elemente festlegen. Dies liegt daran, dass wir das <router-outlet> in MyNavComponent haben und immer wenn wir auf eine dieser beiden Routen treffen, rendern wir die untergeordnete Komponente, an der das <router-outlet> platziert wurde.

Danach sollten wir beim Bereitstellen der App Folgendes sehen:

Die Links auf der linken Seite wurden durch Add Memory und View My Memories ersetzt, wobei letzteres ausgewählt ist. Der leere Bereich enthält jetzt eine Tabelle mit ID-Nummern und Namen.

Erstellen Sie die App (Ein Tagebuch der Erinnerungen)

Okay, jetzt erstellen wir das Formular, um neue Erinnerungen in unserem Tagebuch zu speichern.

Wir müssen einige Materialmodule und das Formularmodul in unsere app.module.ts :

 import { FormsModule } from '@angular/forms'; import { MatCardModule, MatFormFieldModule, MatInputModule, MatDatepickerModule, MatNativeDateModule } from '@angular/material'; // ... Imports:[ // ... MatCardModule, MatFormFieldModule, MatInputModule, MatDatepickerModule, FormsModule, MatNativeDateModule, // ... ]

Und dann fügen wir in add-memory.component.html das Formular hinzu:

 <form #form="ngForm" (ngSubmit)="onSubmit()"> <mat-card class="memory-card"> <mat-card-title> Add a memory </mat-card-title> <mat-card-content> <mat-form-field> <input disabled matInput placeholder="Select the date..." [(ngModel)]="memory.date" name="date" [matDatepicker]="date"> <mat-datepicker-toggle matSuffix [for]="date"></mat-datepicker-toggle> <mat-datepicker disabled="false" #date></mat-datepicker> </mat-form-field> <mat-form-field> <textarea placeholder="Enter your memory..." rows="3" maxlength="300" matInput [(ngModel)]="memory.text" name="memory"></textarea> </mat-form-field> </mat-card-content> <mat-card-actions> <button mat-button type="submit">Save me!</button> </mat-card-actions> </mat-card> </form> <pre> {{ memory | json }} </pre>

Hier verwenden wir eine mat-card und fügen zwei Felder hinzu, ein date und einen textarea .

Beachten Sie, dass wir [(ngModel)] . Diese Angular-Direktive bindet den Ausdruck memory.date und die Eigenschaft „ memory “ in der Klasse aneinander, wie wir später sehen werden. ( [(ngModel)] ist syntaktischer Zucker – eine Abkürzung, um eine bidirektionale Datenbindung von der Klasse zur Ansicht und von der Ansicht zur Klasse durchzuführen. Das bedeutet, dass memory.date diese Änderungen widerspiegelt, wenn Sie Text in die Ansicht eingeben in der Klasseninstanz, und wenn Sie Änderungen an memory.date in der Klasseninstanz vornehmen, spiegelt die Ansicht die Änderungen wider.)

In add-memory.component.ts der Code so aus:

 import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-add-memory', templateUrl: './add-memory.component.html', styleUrls: ['./add-memory.component.scss'] }) export class AddMemoryComponent implements OnInit { memory: any = {}; constructor() { } ngOnInit() { } onSubmit() { console.log(this.memory); } }

Hier initialisieren wir die über ngModel gebundene memory . Wenn die AddMemoryComponent Komponente instanziiert wird, ist der memory ein leeres Objekt. Wenn dann die ngModel Direktive ausgeführt wird, kann sie den Eingabewert memory.date und memory.text . Wenn wir dies nicht tun würden, würden wir einen Fehler von Cannot set property 'date/text' of undefined erhalten.

In der Zwischenzeit muss add-memory.component.scss haben:

 .memory-card { min-width: 150px; max-width: 400px; width: 100%; margin: auto; } .mat-form-field { width: 100%; }

Da wir <pre> {{ memory | json }} </pre> <pre> {{ memory | json }} </pre> können wir den aktuellen Zustand des memory in der Ansicht sehen. Wenn wir zum Browser gehen, hier ist das bisherige Ergebnis:

Der Prototyp der Tagebuch-App "my-memories", der die interne Darstellung der Benutzereingaben (Datum und Text) zeigt.

In der Ansicht haben wir das Formular über (ngSubmit)="onSubmit()" an die Funktion onSubmit in der Klasse gebunden.

 onSubmit() { console.log(this.memory); }

Wenn Sie also auf „Save me!“ klicken, Schaltfläche erhalten Sie die interne Darstellung der Benutzereingabe, die an das Konsolenprotokoll gesendet wird:

Die interne Darstellung der Benutzereingabe im Konsolenprotokoll.

Angular 6-Tutorial: Mit Firebase verbinden

Als nächstes verbinden wir unser Projekt mit Firebase, um unsere Erinnerungen zu speichern.

Zuerst gehen wir zur Firebase-Konsole und erstellen dort ein Projekt.

Hinzufügen eines Firebase-Projekts.

Zweitens installieren wir die Pakete firebase und angularfire2 :

 npm install firebase angularfire2 --save

Und dann in jeder dieser drei Dateien:

  1. /src/environments/environment.ts
  2. /src/environments/environment.hmr.ts
  3. /src/environments/environment.prod.ts

… fügen wir unsere Firebase-Konfiguration hinzu:

 export const environment = { // ... firebase: { apiKey: '<your-key>', authDomain: '<your-project-authdomain>', databaseURL: '<your-database-URL>', projectId: '<your-project-id>', storageBucket: '<your-storage-bucket>', messagingSenderId: '<your-messaging-sender-id>' } };

Sie können die erforderlichen Konfigurationsdetails für die oben genannten Dateien abrufen, indem Sie auf der Projektübersichtsseite auf „Firebase zu Ihrer Web-App hinzufügen“ klicken.

Danach fügen wir die Firebase-Module in unsere app.module.ts :

 import { AngularFireModule } from 'angularfire2'; import { AngularFireDatabaseModule } from 'angularfire2/database'; import { environment } from '../environments/environment'; // ... Imports:[ // ... AngularFireModule.initializeApp(environment.firebase), AngularFireDatabaseModule, // ... ]

Und in add-memory.component.ts wir die Datenbank in den Konstruktor ein und speichern die Werte aus dem Formular in der Datenbank. Wenn das Push-Versprechen von Firebase erfolgreich ist, protokollieren wir den Erfolg in der Konsole und setzen das Modell zurück:

 import { AngularFireDatabase } from 'angularfire2/database'; // ... constructor(private db: AngularFireDatabase) { } // ... onSubmit() { this.memory.date = new Date(this.memory.date).valueOf(); this.db.list('memories').push(this.memory) .then(_ => { this.memory = {} console.log('success') }) } 

Lese- und Schreibzugriff auf Ihre Firebase-Datenbank zulassen.

Sie müssen den öffentlichen Zugriff auf die Datenbankregeln zulassen, damit anonyme Benutzer darin lesen und schreiben können. Bitte beachten Sie, dass mit dieser Einrichtung jeder Benutzer Ihre App-Daten lesen/ändern/löschen kann. Stellen Sie sicher, dass Sie Ihre Regeln entsprechend einrichten, bevor Sie in die Produktion gehen.

Um die Umgebungsänderungen zu übernehmen, müssen Sie außerdem den ng serve Prozess neu starten.

Wenn wir jetzt zum Browser zurückkehren und auf unsere Speichern-Schaltfläche klicken, sehen wir, dass der Speicher zur Datenbank hinzugefügt wurde:

Unser Testspeicher wurde der Firebase-Datenbank unserer Tagebuch-App hinzugefügt.

Werfen wir einen Blick darauf, wie wir unsere Erinnerungen abrufen und in der Materialtabelle anzeigen können.

Als wir damals die Tabelle mit ng generate @angular/material:material-table --name=view-memories', we automatically got a file view-memories/view-memories-datasource.ts`. Diese Datei enthält gefälschte Daten, daher müssen wir sie ändern, um mit dem Abrufen von Firebase zu beginnen.

In view-memories-datasource.ts entfernen wir die EXAMPLE_DATA und legen ein leeres Array fest:

 export class ViewMemoriesDataSource extends DataSource<ViewMemoriesItem> { data: ViewMemoriesItem[] = []; // ...

Und in getSortedData aktualisieren wir die Feldnamen:

 private getSortedData(data: ViewMemoriesItem[]) { if (!this.sort.active || this.sort.direction === '') { return data; } return data.sort((a, b) => { const isAsc = this.sort.direction === 'asc'; switch (this.sort.active) { case 'text': return compare(a.name, b.name, isAsc); case 'date': return compare(+a.id, +b.id, isAsc); default: return 0; } }); }

In view-memories.component.html aktualisieren wir die Spaltennamen auf date und text aus unserem Speichermodell. Beachten Sie, dass wir, da wir das Datum im Millisekundenformat gespeichert haben, hier eine Datumspipe verwenden, um den Wert für die Anzeige in ein menschenfreundlicheres Datumsformat umzuwandeln. Zuletzt entfernen wir [length]="dataSource.data.length" aus dem Paginator, da wir Daten asynchron von Firebase laden:

 <div class="mat-elevation-z8"> <table mat-table #table [dataSource]="dataSource" matSort aria-label="Elements"> <!-- Id Column --> <ng-container matColumnDef="date"> <th mat-header-cell *matHeaderCellDef mat-sort-header>Date</th> <td mat-cell *matCellDef="let row">{{row.date | date:'short'}}</td> </ng-container> <!-- Name Column --> <ng-container matColumnDef="text"> <th mat-header-cell *matHeaderCellDef mat-sort-header>Text</th> <td mat-cell *matCellDef="let row">{{row.text}}</td> </ng-container> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> </table> <mat-paginator #paginator [pageIndex]="0" [pageSize]="50" [pageSizeOptions]="[25, 50, 100, 250]"> </mat-paginator> </div>

Ändern Sie die view-memories.component.css in view-memories.component.scss und legen Sie den Tabellenstil fest:

 table{ width: 100%; }

In view-memories.component.ts ändern wir die styleUrls , um die obige Umbenennung in ./view-memories.component.scss . Wir aktualisieren auch das Array displayedColumns auf ['date', 'text'] und richten die Tabellendatenquelle ein, um Daten von Firebase abzurufen.

Was hier passiert, ist, dass wir die Erinnerungsliste abonnieren und wenn wir die Daten erhalten, instanziieren wir die ViewMemoriesDataSource und setzen ihre Dateneigenschaft mit den Daten von Firebase.

 this.subscription = this.db.list<ViewMemoriesItem>('memories').valueChanges().subscribe(d=>{ console.log('data streaming'); this.dataSource = new ViewMemoriesDataSource(this.paginator, this.sort); this.dataSource.data = d; });

Firebase gibt ein Observable-Array im ReactiveX-Stil zurück.

Beachten Sie, dass wir this.db.list<ViewMemoriesItem>('memories') — die aus dem Pfad 'memories' gezogenen Werte — in ViewMemoriesItem . Dafür sorgt die angularfire2 Bibliothek.

Wir haben auch den unsubscribe -Aufruf in den onDestroy Hook des Lebenszyklus der Angular-Komponente aufgenommen.

 import { Component, OnInit, ViewChild, OnDestroy } from '@angular/core'; import { MatPaginator, MatSort } from '@angular/material'; import { ViewMemoriesDataSource, ViewMemoriesItem } from './view-memories-datasource'; import { AngularFireDatabase } from 'angularfire2/database'; import { Subscription } from 'rxjs'; import { map, first } from 'rxjs/operators'; @Component({ selector: 'app-view-memories', templateUrl: './view-memories.component.html', styleUrls: ['./view-memories.component.scss'] }) export class ViewMemoriesComponent implements OnInit, OnDestroy{ @ViewChild(MatPaginator) paginator: MatPaginator; @ViewChild(MatSort) sort: MatSort; dataSource: ViewMemoriesDataSource; /** Columns displayed in the table. Columns IDs can be added, removed, or reordered. */ displayedColumns = ['date', 'text']; subscription: Subscription; constructor(private db: AngularFireDatabase) { } ngOnInit() { this.subscription = this.db.list<ViewMemoriesItem>('memories').valueChanges().subscribe(d=>{ console.log('data streaming'); this.dataSource = new ViewMemoriesDataSource(this.paginator, this.sort); this.dataSource.data = d; }); } ngOnDestroy(): void { this.subscription.unsubscribe(); } }
Verwandt: Erstellen von mobilen Echtzeitanwendungen für mehrere Plattformen: Beispiele mit Ionic Framework und Firebase

Bereitstellung auf Firebase-Hosting

Um unsere App nun live zu schalten, stellen wir sie auf Firebase Hosting bereit. Dazu installieren wir die Firebase-CLI, die den firebase Befehl verfügbar macht:

 npm install -g firebase-tools

Jetzt können wir uns mit Firebase CLI anmelden:

 firebase login

Dies fordert Sie auf, Ihr Google-Konto auszuwählen.

Als Nächstes initialisieren wir das Projekt und konfigurieren das Firebase-Hosting:

 firebase init

Wir wählen einfach die Hosting-Option aus.

Als nächstes, wenn wir nach dem Pfad gefragt werden, setzen wir ihn auf dist/my-memories . Wenn wir gefragt werden, ob wir es als Single-Page-App konfigurieren sollen (dh alle URLs in /index.html ), antworten wir mit „Ja“.

Schließlich treffen wir auf „Datei dist/my-memories/index.html existiert bereits. Überschreiben?" Hier sagen wir „nein“.

Dadurch werden die Firebase-Konfigurationsdateien .firebaserc und firebase.json mit der bereitgestellten Konfiguration erstellt.

Der letzte Schritt besteht darin, Folgendes auszuführen:

 ng build --prod firebase deploy

Und damit haben wir die App in Firebase veröffentlicht, die eine URL bereitstellt, zu der wir navigieren können, z. B. https://my-memories-b4c52.firebaseapp.com/view-memories, wo Sie meine eigenen veröffentlichten sehen können Demo.


Wow, du hast das Tutorial durch! Ich hoffe, dass es Ihnen gefallen hat. Sie können sich auch den vollständigen Code dafür auf GitHub ansehen.

Ein Schritt auf einmal

Angular ist ein sehr leistungsfähiges Framework zum Erstellen von Web-Apps. Es ist schon lange auf dem Markt und hat sich sowohl für kleine, einfache Apps als auch für große, komplexe Apps bewährt – Angular 6 ist hier keine Ausnahme.

Für die Zukunft plant Angular, sich weiter zu verbessern und neuen Webparadigmen wie Webkomponenten (Angular Elements) zu folgen. Wenn Sie daran interessiert sind, Hybrid-Apps zu erstellen, können Sie sich Ionic ansehen, das Angular als zugrunde liegendes Framework verwendet.

Dieses Tutorial behandelte sehr grundlegende Schritte, um mit der Verwendung von Angular, Material und Firebase zu beginnen. Sie sollten jedoch berücksichtigen, dass Sie für reale Anwendungen eine Validierung hinzufügen müssen, und um Ihre Anwendung leichter zu warten und zu skalieren, sollten Sie wahrscheinlich Best Practices wie die Verwendung von Diensten, wiederverwendbaren Komponenten usw. befolgen Das muss Thema eines anderen Artikels sein – hoffentlich hat dieser ausgereicht, um Ihren Appetit auf die Angular-Entwicklung zu wecken!

Verwandte: Alle Vorteile, kein Ärger: Ein Angular 9-Tutorial