Angular 6 教程:具有新功能的新功能

已發表: 2022-03-11

Angular 6 出來了! 最突出的變化在於它的 CLI 以及服務的注入方式。 如果您希望在本教程中編寫您的第一個 Angular 6 應用程序(或 Angular/Firebase 應用程序),我們將介紹初始設置的基本步驟並創建一個小型日記應用程序。

Angular 6:基礎知識

如果您以前從未使用過 Angular,讓我簡要介紹一下它以及它是如何工作的。

Angular 是一個 JavaScript 框架,旨在支持為桌面和移動設備構建單頁應用程序 (SPA)。

該框架包括一整套指令和模塊,可讓您輕鬆實現 Web 應用程序的一些最常見場景,如導航、授權、表單和報告。 它還附帶了所有必要的包,以使用 Jasmine 框架添加測試並使用 Karma 或 Protractor 測試運行器運行它們。

Angular 架構基於組件、模板、指令和服務。 它為你的服務提供了一個內置的依賴注入機制,以及雙向數據綁定來連接你的視圖和你的組件代碼。

Angular 使用 TypeScript,一個 JS 的類型化超集,它會讓一些事情變得更容易,特別是如果你來自類型化語言背景。

Angular 6:新功能

Angular 6 新特性的簡要總結:

  • 為框架包( @angular/core@angular/common@angular/compiler等)、CLI、Material 和 CDK 同步主要版本號的策略。 這將有助於使交叉兼容性更加清晰:您可以通過快速瀏覽版本號來判斷關鍵包是否相互兼容。
  • 新的ng CLI 命令:
    • ng update智能升級包版本,更新依賴版本並保持同步。 (例如,當運行ng update @angular/core時,所有框架以及 RxJS 都會被更新。)如果包中包含原理圖,它也會運行原理圖。 (如果較新的版本包含需要更改代碼的重大更改,則原理圖將為您更新您的代碼。)
    • ng add添加新包(並運行腳本,如果適用)
  • 服務現在引用將提供它們的模塊,而不是像過去那樣引用服務的模塊。

作為最後一次更改含義的示例,您的代碼過去看起來像這樣:

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

…隨著 Angular 6 的這一特殊變化,它看起來像:

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

這些被稱為可搖樹的提供程序,允許編譯器刪除未引用的服務,從而生成更小的包。

角 6 CLI

ng命令行界面是 Angular 的一個非常重要的部分,它允許您在編寫應用程序時更快地移動。

使用 CLI,您可以非常輕鬆地搭建初始應用程序設置、生成新組件、指令等,並在本地環境中構建和運行應用程序。

創建 Angular 6 項目

好了,說夠了。 讓我們動手並開始編碼。

首先,您需要在機器上安裝 Node.js 和 npm。

現在,讓我們繼續安裝 CLI:

 npm install -g @angular/cli

由於-g開關,這將全局安裝ng CLI 命令。

一旦我們有了它,我們就可以使用ng new為我們的應用程序獲取初始腳手架:

 ng new my-memories --style=scss

這將創建一個my-memories文件夾,創建所有必要的文件以使您的初始設置準備好開始,並安裝所有必要的軟件包。 --style=scss開關是可選的,它將設置編譯器將 SCSS 文件編譯為 CSS,我們稍後將需要它。

安裝完成後,您可以cd my-memories並運行ng serve 。 這將啟動構建過程和在http://localhost:4200為您的應用程序提供服務的本地 Web 服務器。

搭建腳手架後的 Angular 6 應用程序

幕後發生的事情是 CLI 將所有.ts (TypeScript 文件)轉換為 vanilla JS,從包文件夾node_modules收集所有必需的依賴項,並將結果輸出到一組文件中,這些文件通過本地 Web 服務器提供服務在端口 4200 上運行。

項目文件

如果你不熟悉 Angular 的項目文件夾結構,你需要知道的最重要的事情是所有與應用程序相關的代碼都在src文件夾中。 您通常會按照您的應用架構(例如用戶、購物車、產品)在該文件夾中創建所有模塊和指令。

Angular 6 項目文件夾結構

最初設定

好的,到目前為止,我們已經完成了應用程序的初始設置。 讓我們開始做一些改變。

在開始之前,讓我們深入了解一下src文件夾。 初始頁面是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>

在這裡,我們看到了一些基本的 HTML 和<app-root>標籤。 這是一個 Angular 組件,Angular 6 在其中插入了我們的組件代碼。

我們將找到app/app.component.ts文件,該文件具有選擇器app-root以匹配index.html文件中的內容。

該組件是一個修飾的 TypeScript 類,在這種情況下,包含title屬性。 @Component裝飾器告訴 Angular 在類中包含組件行為。 除了選擇器之外,它還指定要呈現的 HTML 文件以及要使用的樣式表。

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

如果我們查看app.component.html ,我們會看到{{title}}插值綁定。 這是所有魔術綁定發生的地方,Angular 將呈現類 title 屬性的值,並在它發生變化時更新它。

 <!--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>

讓我們繼續將課程的title更新為'My Memories!' .

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

我們將看到編譯器處理我們的更改並且瀏覽器刷新以顯示我們更新的標題。

這意味著 Angular 6 的ng serve監視我們的文件更改,並在每次將更改引入任何文件時進行渲染。

為了使編碼更加友好並避免每次進行更改時都刷新整個頁面,我們可以利用 webpack 熱模塊替換(HMR),它只是更新被更改的 JS/CSS 塊,而不是產生完整的刷新顯示您的更改。

配置 HMR

首先,我們需要設置環境。

創建一個包含以下內容的文件src/environments/environment.hmr.ts

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

更新src/environments/environment.prod.ts並將hmr: false標誌添加到環境中:

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

然後更新src/environments/environment.ts並將hmr: false標誌添加到那裡的環境中:

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

接下來在angular.json文件中,更新這部分:

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

projectsmy-memoriesarchitectserveconfigurations下:

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

現在通過在compilerOptions下添加以下內容來更新tsconfig.app.json以包含必要的types (好吧,類型):

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

接下來,我們將安裝@angularclass/hmr模塊作為開發依賴項:

 npm install --save-dev @angularclass/hmr

然後通過創建文件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(); }); };

接下來,更新src/main.ts以使用上述功能:

 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)); }

我們在這裡做的是讓 bootstrap 調用一個匿名函數,然後詢問environment.hmr標誌是否為真。 如果是,我們從hmr.ts中調用之前定義的函數來啟用熱模塊替換; 否則,我們像以前一樣引導它。

現在,當我們運行ng serve --hmr --configuration=hmr時,我們將調用hmr配置,當我們對文件進行更改時,我們將獲得更新而無需完全刷新。 第一個--hmr用於 webpack,--configuration --configuration=hmr用於 Angular 使用hmr環境。

漸進式 Web 應用程序 (PWA)

為了添加 Angular 6 PWA 支持並啟用應用程序的離線加載,我們可以使用新的 CLI 命令之一ng add

 ng add @angular/[email protected]

請注意,我正在添加版本,因為我在編寫本教程時的最新版本引發了錯誤。 (您可以嘗試不使用它並使用簡單的ng add @angular/pwa檢查它是否適合您。)

好的,所以在我們運行命令之後,我們會看到我們的項目發生了很多變化。 最重要的變化是它增加了:

  • angular.json資產文件中manifest.json的引用,以便它包含在構建輸出中,以及"serviceWorker": true在生產構建中
  • 具有初始設置的ngsw-config.json文件,用於緩存應用程序運行所需的所有文件
  • index.html文件中的manifest.json元標記
  • manifest.json文件本身,包含應用程序的基本配置
  • 應用程序模塊ServiceWorkerModule.register('/ngsw-worker.js', { enabled: environment.production })中的 service worker 負載(注意 service worker 只會在生產環境中啟用)

所以,這意味著當用戶第一次訪問 URL 時,文件將被下載。 之後,如果用戶嘗試在沒有網絡服務的情況下訪問 URL,應用程序仍然可以通過拉取這些緩存文件來工作。

添加 Material Angular 6 UI 庫

到目前為止,我們已經完成了初始設置,並且準備開始構建我們的應用程序。 要利用已經構建的組件,我們可以使用 Angular 6 版本的 Material。

為了在我們的應用程序上安裝material包,我們將再次使用ng add

 ng add @angular/material

運行之後,我們會看到添加了一些新的包和一些基本的樣式配置:

  • index.html包括 Roboto 字體和 Material 圖標
  • BrowserAnimationsModule被添加到我們的AppModule
  • angular.json已經為我們包含了靛藍粉色主題

表明您選擇的預建 Angular 6 主題

您需要重新啟動ng serve以獲取主題,或者您可以選擇另一個預建主題。

相關:使用 Angular Material 構建超現代 Web 應用程序

基本佈局

為了獲得初始的 sidenav 佈局,我們將使用 Material 附帶的示意圖。 但是如果你想使用不同的佈局也沒關係。

(簡而言之,原理圖可讓您將轉換應用到項目:您可以根據需要創建、修改或刪除文件。在這種情況下,它為我們的應用程序搭建了一個側導航佈局。)

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

這將創建一個 sidenav 組件,並準備好啟動最低設置。 那不是很棒嗎?

它還在我們的app.module.ts中包含了所有必要的模塊。

一個新創建的“my-nav”Angular 6 組件

由於我們使用的是 SCSS,我們需要將my-nav.component.css文件重命名為my-nav.component.scss ,並在my-nav.component.ts中更新相應的引用styleUrls以使用新名稱。

現在要使用新組件,讓我們轉到app.component.html並刪除所有初始代碼,只留下:

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

當我們返回瀏覽器時,我們將看到以下內容:

四窗格佈局,左上角有菜單,旁邊是我的記憶,菜單下有三個編號的鏈接;第四個窗格是空的

讓我們更新鏈接以僅包含我們想要的兩個選項。

首先,讓我們創建兩個新組件:

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

(第二個是用於創建表格的材料示意圖。)

接下來,在my-nav上,我們將更新以設置鏈接並包含<router-outlet>以顯示我們的內容組件:

 <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>

此外,在app.component.html中,我們需要將其更新為僅具有主<router-outlet> (即刪除<my-nav> ):

 <router-outlet></router-outlet>

接下來,在AppModule中,我們將包含路由:

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

請注意,我們將MyNavComponent設置為父級,並將我們創建的兩個組件設置為子級。 這是因為我們在MyNavComponent中包含了<router-outlet> ,並且每當我們點擊這兩個路由之一時,我們將渲染放置<router-outlet>的子組件。

在此之後,當我們提供應用程序時,我們應該看到:

左側鏈接已替換為“添加內存”和“查看我的記憶”,後者已被選中。空窗格現在有一個帶有 ID 號和名稱的表。

構建應用程序(回憶日記)

好的,現在讓我們創建表單來將新的記憶保存到我們的日記中。

我們需要將一些材料模塊和表單模塊導入到我們的app.module.ts

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

然後在add-memory.component.html中,我們將添加表單:

 <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>

在這裡,我們使用mat-card並添加兩個字段,一個date和一個textarea

請注意,我們正在使用[(ngModel)] 。 這個 Angular 指令將類中的memory.date表達式和memory屬性相互綁定,我們稍後會看到。 ( [(ngModel)]是語法糖——執行從類到視圖以及從視圖到類的雙向數據綁定的快捷方式。這意味著當您在視圖中輸入文本時, memory.date將反映這些更改在類實例中,如果您在類實例中對memory.date進行更改,視圖將反映更改。)

add-memory.component.ts中,代碼將如下所示:

 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); } }

在這裡,我們正在初始化通過ngModel綁定的memory屬性。 當AddMemoryComponent組件被實例化時, memory將是一個空對象。 然後當ngModel指令運行時,它將能夠將輸入值分配給memory.datememory.text 。 如果我們不這樣做,我們會收到Cannot set property 'date/text' of undefined的錯誤。

同時, add-memory.component.scss需要有:

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

因為我們有<pre> {{ memory | json }} </pre> <pre> {{ memory | json }} </pre>我們可以在視圖中看到memory的當前狀態。 如果我們轉到瀏覽器,到目前為止的結果如下:

“我的記憶”日記應用原型,顯示用戶輸入(日期和文本)的內部表示。

在視圖中,我們通過(ngSubmit)="onSubmit()"將表單綁定到類中的onSubmit函數。

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

所以當你點擊“救救我!” 按鈕,您將獲得發送到控制台日誌的用戶輸入的內部表示:

控制台日誌中用戶輸入的內部表示。

Angular 6 教程:與 Firebase 連接

我們接下來要做的是將我們的項目連接到 Firebase 以保存我們的記憶。

首先,我們將轉到 Firebase 控制台並在那裡創建一個項目。

添加 Firebase 項目。

其次,我們將安裝firebaseangularfire2包:

 npm install firebase angularfire2 --save

然後在這三個文件中的每一個中:

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

…我們將添加我們的 Firebase 配置:

 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>' } };

您可以通過單擊項目概述頁面上的“將 Firebase 添加到您的網絡應用程序”來獲取上述文件所需的配置詳細信息。

之後,我們將在app.module.ts中包含 Firebase 模塊:

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

add-memory.component.ts中,我們在構造函數中註入數據庫並將表單中的值保存到數據庫中。 當 Firebase 的推送承諾成功時,我們在控制台中記錄成功並重置模型:

 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') }) } 

允許對您的 Firebase 數據庫進行讀寫訪問。

您需要允許對數據庫規則進行公共訪問,以便匿名用戶可以對其進行讀取和寫入。 請注意,通過此設置,任何用戶都可以讀取/更改/刪除您的應用數據。 確保在投入生產之前相應地設置規則。

此外,要獲取環境更改,您需要重新啟動ng serve進程。

現在,當我們返回瀏覽器並單擊保存按鈕時,我們將看到內存已添加到數據庫中:

我們的測試內存已添加到日記應用的 Firebase 數據庫中。

讓我們看一下如何檢索我們的記憶並將它們顯示在 Material 表中。

當我們使用ng generate @angular/material:material-table --name=view-memories', we automatically got a file view-memories/view-memories-datasource.ts`。 此文件包含虛假數據,因此我們需要對其進行更改以開始從 Firebase 中提取數據。

view-memories-datasource.ts中,我們將刪除EXAMPLE_DATA並設置一個空數組:

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

getSortedData我們將更新字段名稱:

 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; } }); }

view-memories.component.html中,我們將列名更新為來自內存模型的datetext 。 請注意,由於我們以毫秒格式保存日期,因此這裡我們使用日期管道將值轉換為更人性化的日期格式顯示。 最後,我們從分頁器中刪除[length]="dataSource.data.length" ,因為我們將從 Firebase 異步加載數據:

 <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>

view-memories.component.css更改為view-memories.component.scss並設置表格樣式:

 table{ width: 100%; }

view-memories.component.ts中,我們將更改styleUrls以反映上述重命名為./view-memories.component.scss 。 我們還將displayedColumns數組更新為['date', 'text']並設置表數據源以從 Firebase 獲取數據。

這裡發生的事情是我們訂閱了內存列表,當我們收到數據時,我們實例化ViewMemoriesDataSource並使用來自 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 返回一個 ReactiveX 風格的 Observable 數組。

請注意,我們將this.db.list<ViewMemoriesItem>('memories')'memories'路徑中提取的值)轉換為ViewMemoriesItem 。 這由angularfire2庫負責。

我們還將unsubscribe調用包含在 Angular 組件生命週期的onDestroy掛鉤中。

 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(); } }
相關:構建實時、多平台的移動應用程序:使用 Ionic 框架和 Firebase 的示例

部署到 Firebase 託管

現在,為了讓我們的應用上線,讓我們將其部署到 Firebase 託管。 為此,我們將安裝 Firebase CLI,它使firebase命令可用:

 npm install -g firebase-tools

現在我們可以使用 Firebase CLI 登錄:

 firebase login

這將提示您選擇您的 Google 帳戶。

接下來,我們將初始化項目並配置 Firebase 託管:

 firebase init

我們將只選擇託管選項。

接下來,當我們被要求提供路徑時,我們會將其設置為dist/my-memories 。 當我們被問到是否將其配置為單頁應用程序時(即將所有 URL 重寫為/index.html ),我們會回答“是”。

最後,我們會點擊,“文件 dist/my-memories/index.html 已經存在。 覆蓋?” 在這裡,我們會說“不”。

這將使用提供的配置創建firebase.json配置文件.firebaserc和 firebase.json。

最後一步是運行:

 ng build --prod firebase deploy

有了這個,我們將把應用程序發佈到 Firebase,它提供了一個 URL 供我們導航,例如 https://my-memories-b4c52.firebaseapp.com/view-memories,您可以在其中查看我自己發布的演示。


哇,你已經完成了教程! 我希望你喜歡它。 你也可以在 GitHub 上查看它的完整代碼。

一步一步來

Angular 是一個非常強大的構建 Web 應用程序的框架。 它已經存在了很長時間,並且已經證明了自己適用於小型、簡單的應用程序和大型、複雜的應用程序——Angular 6 在這裡也不例外。

展望未來,Angular 計劃不斷改進並遵循新的 Web 範例,例如 Web 組件(Angular Elements)。 如果您對構建混合應用程序感興趣,可以查看使用 Angular 作為其底層框架的 Ionic。

本教程涵蓋了開始使用 Angular、Material 和 Firebase 的非常基本的步驟。 但是您應該考慮到,對於實際應用程序,您需要添加驗證,並且為了使您的應用程序更易於維護和擴展,您可能希望遵循最佳實踐,例如使用服務、可重用組件等. 這將是另一篇文章的主題——希望這篇文章足以激起你對 Angular 開發的興趣!

相關:所有特權,無後顧之憂:Angular 9 教程