Angular 教學

Angular 心得分享 (1)

教學目標

初步了解 Angular 框架在企業中如何實務應用的情況,以下內容為心得筆記分享。

重點概念

參加完台灣 Angular 社群小聚:用企業級的平台在前端世界乘風破浪的活動之後,對於 Angular 有更進一步的認識,其中最有收獲的三個議程,分別為:

  1. Angular 與 PWA - Offline WebSite
  2. 企業導入 Angular 作為前端開發架構的好處
  3. 優化 Angular 團隊開發流程:實現 DevOps 開發維運一體化

Angular 與 PWA - Offline WebSite

首先 Progressive Web Apps 是一種在網際網路中交付更佳使用者體的方法,簡單來說使用者直接透過瀏覽器進行存取,不需要安裝應用,同時隨著使用者應用的時間越來越長時,則將會載入更快速,即便是在糟糕的網路環境中,也能夠提供良好的使用者體驗,而非直接斷線,同時支援推播服務和新增至主畫面圖示等行動裝置中原生應用,其主要有三大特點分別為:

可靠

瞬間載入,且在不確定的網路條件下也不會顯示錯誤。

快速

快速回應的使用者互動,且支援流暢的互動動畫。

參與

感覺是在行動裝置上原生應用的應用程式,提供沉浸式的使用者體驗。

但是重點則在於如何透過 Angular 製作 Progressive Web Apps 進行離線瀏覽的應用,主要重點在於了解 Service Worker 的生命週期,當沒有 Service Worker 時則會進行 Installing ,接著進行 Actived,再來就透過 Fetch 進行針對請求回應進行快取的處理。在了解基本概念之後就進行 Angular 實作,實作除了手動建立處理快取之外,更可以透過工具直接產生,主要工具有三種 sw-toolbox 、 sw-precache 和 workbox ,其中 sw-toolbox 最基本、 sw-precache 最成熟,以及 workbox 最新且支援 Google Analytics 的離線追蹤應用。

企業導入 Angular 作為前端開發架構的好處

接著企業導入 Angular 框架對於前端的好處,總共有四大好處,分別為:

團隊內部後端工程師居多

  • 熟悉物件導向
  • 熟悉強類型
  • 熟悉依賴注入

從 MVC 改成前後端分離

  • 企業內部各系統會互相呼叫使用
  • 同時有網際網路與行動裝置需求
  • 後端只寫 JSON,避免處理視圖

商業邏輯複雜

  • 編譯技術
  • 單元測試
  • 強力重構

統一且好維護的框架

  • 維護困難,需要統一的開發規範風格
  • 不用太依賴太多第三方套件,而是整套框架
  • 統一的目錄架構

因此導入 Angular 前端框架能夠為企業帶來更多的好處,尤其提供大型應用程式開發與規範最完善的解決方案。

優化 Angular 團隊開發流程:實現 DevOps 開發維運一體化

再來 Angular 實現 DevOps 開發維運一體化,主要則提到在 DevOps 不同階段如何透過 Angular 進行優化。

開發流程

首先開發流程,主要為規劃、建立和驗證,開發時初步將每個頁面就是一元件封裝成模組,一般來說我們規劃應用程式時,會先了解功能清單、網站地圖、網頁線稿、設計提案和前端切版,當了解之後就能夠透過 Angular 框架快速打造應用程式。

建立 Angular 專案

主要透過 Angular CLI。

1
$ ng new myapp --routing

建立 Angular 模組

主要依網站地圖分組,然而 app-module 需要手動匯入模組才能使用,主要在 imports 中使用。。

1
$ ng g m module --routing -m=app

建立 Angular 元件

主要依據網站地圖中的每個頁面。

1
$ ng g c module1/page1 -m=module1

依據模組進行工作切割與專案分工。

依據實際需求建立必要的 Angular 元件,接著定義模組下的路由,再來將所有頁面進行串連。

程式碼風格檢查

主要工具有 codelyzer 、 ng lint 和 TSLint。

1
$ ng lint

單元測試開發

主要工具有 Karma 、 Jasmine 和 Protrator。

部署流程

最後部署流程,主要為打包、發佈和設定,一開始會先建立部署檔案,主要有三件重要的事情要非常注意,第一切換建置環境,主要設定 package.json 檔案、第二部署多重應用程式,主要設定 angular-cli.json,第三佈署虛擬目錄,主要針對部署時相對路徑不同的問題進行處理。接著透過雲端服務進行持續整合和持續部署,關鍵重點在於以下三個指令,當持續整合和持續部署完成之後就能夠進行發佈了。除此之外 Angular 框架支援自訂錯誤監控處理器,以利我們有效進行錯誤控管。

1
2
3
$ npm install
$ npm run lint
$ npm run build-prod

總結參加完台灣 Angular 社群小聚,更加了解 Angular 框架在於企業中的實務應用的情況,以及如何導入之後如何有效整合應用至 DevOps 開發與維運的流程中。

相關資源

Angular 基本介紹 (6)

教學目標

初步了解 Angular 綁定語法基本概念與應用。

重點概念

Angular 提供資料綁定是一種機制,主要用來協調使用者應用中所看見的資料。雖然我們能夠透過 HTML 處理資料綁定,但若是透過資料綁定框架處理應用時,將會變得更容易編寫、閱讀和維護,簡單來說只要簡單地在綁定來源和目標 HTML 元素之間聲明綁定,框架就會完成這項工作,一般來說資料綁定的類型根據資料流的方向可以分為三大類:

資料方向 語法 綁定類型
單向(從資料來源到視圖目標) [target]=”expression” 插值表達式
單向(從視圖目標到資料來源) (target)=”statement” 事件
雙向 [(target)]=”expression” 雙向

此時我們要如何在元件內針對資料進行雙向綁定的機制呢? 其實很簡單只要開啟 src/app/login 資料夾中的 login.components.ts 檔案,接著修改程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import { Component, OnInit, Inject} from '@angular/core';
import { AuthService } from '../core/auth.service';
@Component({
selector: 'app-login',
template: `
<div>
Username: <input [(ngModel)]="username" type="text">
<button (click)="onClick()">Login</button>
<br /><br />
{{message}}
</div>
`,
styles: [],
providers:[AuthService]

})
export class LoginComponent implements OnInit {
username = "";
message = "Please input username and click login button.";
constructor(@Inject('auth') private service) {

}

ngOnInit() {
}

onClick() {
if (this.service.loginWithCredentials(this.username)) {
this.message = this.username + " login successful.";
} else {
this.message = this.username + " login fail.";
}
}
}

我們主要是透過 [(ngModel)]=”username” 進行 username 變數資料的雙向綁定,就是說 HTML 對應控制元件的狀態會改變會反射設定至元件中的 Model 中,其中 ngModel 是 FormModule 提供的指令,主要負責從 Domain Model 中建立一個 FormControl 的實體,並且將這個實體和表單的控制元件綁定起來。同時我們針對 click 事件處理不再需要傳入參數,但變數必須先宣告為全域,以及使用變數時必須加上 this. 關鍵字進行使用。

最後重新整理瀏覽器,我們將可以在輸入框中輸入使用者名稱,並且按下登入按鈕,此時只有當輸入「Leo Yeh」時畫面下方將會顯示「login successful.」的訊息,否則顯示「login fail.」的訊息。因此我們為了讓應用程式的程式碼變得更容易編寫、閱讀和維護,會經常使用不同類型的資料綁定方式進行實作。

相關資源

Angular 基本介紹 (5)

教學目標

初步了解 Angular 依賴性注入的基本概念與應用。

重點概念

Angular 所提供的依賴注入框架能夠即時地創建和交付所信賴的服務,並且是個非常重要的程式設計模式,簡稱為 DI。首先為什麼需要依賴注入呢? 若我們只透過元件中的 import 進行匯入服務進行實體化使用時,則會造成緊耦合的問題,此時我們就可以透過依賴注入的方式降低程式碼之間的耦合度。

首先我們針對應用程式中的使用者登入的操作中建立完成業務邏輯的服務,此時服務稱為 AuthService,請先建立 src/app/core 資料夾,接著輸入 ng g s core/auth 指令,其中 ng 代表 Angular CLI 指令、g 代表 generate、s 代表 service,之後在 src/app/core 資料夾中會發現 auth.service.ts 和 auth.service.spec.ts 兩個檔案。

1
2
3
$ cd src/app
$ mkdir core
$ ng g s core/auth

再來我們開啟 auth.service.ts 檔案新增一個登入身份驗證的方法 loginWithCredentials(),簡單的業務邏輯判斷為當使用者為「Leo Yeh」時才代表登入成功,否則失敗。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { Injectable } from '@angular/core';

@Injectable()
export class AuthService {

constructor() { }

loginWithCredentials(username: string): boolean {
if (username === 'Leo Yeh') {
return true;
}
return false;
}
}

雖然我們已經建立完成 AuthService 服務,並且實作業務邏輯,但是還無法在元件中使用,此時我們將會透過依賴注入的方法讓元件使用 AuthService 服務。若我們不使用依賴注入時,則會在 login.component.ts 中匯入 AuthService 服務,並且在建構子中初始化服務,接著在 onClick 事件中使用服務,此時會面臨緊耦合的問題,像是當我們若要修改服務的函數時,則元件也需要進行修改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import { Component, OnInit } from '@angular/core';
import { AuthService } from '../auth.service';
@Component({
selector: 'app-login',
template: `
<div>
Username: <input #usernameRef type="text">
<button (click)="onClick(usernameRef.value)">Login</button>
<br /><br />
{{message}}
</div>
`,
styles: []
})
export class LoginComponent implements OnInit {
service: AuthService;

message = "Please input username and click login button.";
constructor() {
this.service = new AuthService();
}

ngOnInit() {
}

onClick(username) {
if (this.service.loginWithCredentials(username)) {
this.message = username + " login successful.";
} else {
this.message = username + " login fail.";
}
}
}

所以我們改用依賴注入的方式,首先要在 app.module.ts 檔案中匯入 AuthService 服務,並且設定模組中 providers 的服務,其中有兩個屬性 provide 和 useClass ,provide 主要定義服務的名稱,useClass 則指定服務名稱對應的服務的類別。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';

import { AppComponent } from './app.component';
import { LoginComponent } from './login/login.component';
import { AuthService } from './core/auth.service';

@NgModule({
declarations: [
AppComponent,
LoginComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule
],
providers: [{
provide: 'auth', useClass: AuthService
}],
bootstrap: [AppComponent]
})
export class AppModule { }

接著當我們設定完成之後就能夠透過依賴注入的方法使用服務中,請開啟 login.component.ts 檔案進行修改,其中會透過修飾符號 @Inject(‘auth’) 將名稱為 auth 的服務注入至建構函數中,記得要先匯入 Inject 模組。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import { Component, OnInit, Inject} from '@angular/core';
import { AuthService } from '../auth.service';
@Component({
selector: 'app-login',
template: `
<div>
Username: <input #usernameRef type="text">
<button (click)="onClick(usernameRef.value)">Login</button>
<br /><br />
{{message}}
</div>
`,
styles: [],
providers:[AuthService]

})
export class LoginComponent implements OnInit {

message = "Please input username and click login button.";
constructor(@Inject('auth') private service) {

}

ngOnInit() {
}

onClick(username) {
if (this.service.loginWithCredentials(username)) {
this.message = username + " login successful.";
} else {
this.message = username + " login fail.";
}
}
}

最後重新整理瀏覽器,我們將可以在輸入框中輸入使用者名稱,並且按下登入按鈕,此時只有當輸入「Leo Yeh」時畫面下方將會顯示「login successful.」的訊息,否則顯示「login fail.」的訊息。因此我們可以註冊多種類別的提供商,並且透過 @Inject 將服務注入至建構函數中進行服務的實作與應用,以利降低程式碼之間的耦合度。

相關資源

Angular 基本介紹 (4)

教學目標

初步了解 Angular 使用者互動操作的基本概念與應用。

重點概念

使用者互動操作時會觸發 DOM 事件,此時我們將會透過事件綁定進行監聽,接著再將更新之後的資料導入至我們的元件和模組中。在 Angular 中樣板的應用主要管理使用者的呈現畫面和操作行為,並且透過元件類別的樣板與使用者進行互動。從以前使用 MVC (模組-視圖-控制器) 或 MVVM (模型- 視圖-視圖模型) 的經驗中,我們皆熟悉元件和樣板的概成,但在 Angular 中元件扮演著控制器或視圖模型的角色,而樣板則扮演視圖的角色。

首先 HTML 是 Angular 樣板的語言,幾手所有的 HTML 語法皆是有效的樣板語法,除了 script 標籤是被禁用以利阻止腳本注入攻擊的風險。我們可以透過元件和指令以新元素和屬性的使用方式來擴展樣板中的 HTML 應用。

接著透過資料綁定的方式動態獲取和設定 DOM 中的值,此時我們會用到資料綁定的插值表達式,主要透過 把 DOM 中的值插入至 HTML 元素標籤中的內容或者針對標籤的屬性進行值的設定。例如我們先開啟 src/app/login 資料夾中的 login.component.ts 程式碼進行修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import { Component, OnInit } from '@angular/core';

@Component({
selector: 'app-login',
template: `
<div>
Username: <input type="text">
<button >Login</button>
<br /><br />
{{message}}
</div>
`,
styles: []
})
export class LoginComponent implements OnInit {
message = 'Please input username and click login button.';
constructor() { }

ngOnInit() {
}
}

再來重新整理瀏覽器,畫面將會顯示使用者名稱輸入框、登入按鈕和「Please input username and click login button.」的提示訊息,訊息內容主要來自於 LoginComponent 元件中的 message 變數值。但是我們要如何讓使用者輸入名稱且按下登入鈕之後顯示訊息呢?此時我們會用到資料綁定的樣板表達式,主要透過 # 來宣告引用的變數,像是使用者輸入的名稱,以及樣板語句主要是用來回應由綁定目標,像是 HTML 元素、元件或指令所觸發的事件,主要透過 (event)=”statement” 進行事件綁定,其屬於單向資料流之 HTML 元素、元件或指令的事件,例如我們再開啟 src/app/login 資料夾中的 login.component.ts 程式碼進行修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import { Component, OnInit } from '@angular/core';

@Component({
selector: 'app-login',
template: `
<div>
Username: <input #usernameRef type="text">
<button (click)="onClick(usernameRef.value)">Login</button>
<br /><br />
{{message}}
</div>
`,
styles: []
})
export class LoginComponent implements OnInit {
message = 'Please input username and click login button.';
constructor() { }

ngOnInit() {
}

onClick(username) {
this.message = username + " login successful.";
}
}

最後重新整理瀏覽器,我們將可以在輸入框中輸入使用者名稱,並且按下登入按鈕,此時畫面下方將會顯示「login successful.」的訊息。因此在 Angular 中我們可以透過資料綁定的方式動態獲取和設定 DOM 中的值,以及透過事件綁定機制來回應任何 DOM 中的事件,讓使用者進行互動操作的相關應用。

相關資源

Angular 基本介紹 (3)

教學目標

初步了解 Angular 模組的基本概念與應用。

重點概念

首先 Angular 應用具有模組化的特性,被稱為 Angular 模組或 NgModules,基本上每個 Angular 應用至少皆有一個模組,又稱根模組,名稱為 AppModule,根模組在一些小型的應用中是唯一的模組,大多數的應用則會有很多不同特性的模組專注於某領域、工作流程和緊密相關的功能。

接著 Angular 模組皆有一個 @NgModule 裝飾器的類別,@NgModule 接收一個元數據物件,該物件會告訴 Angular 如何進行編譯和執行模組程式碼。主要為模組擁有元件、指令和管道,並且將公開其中一部份讓外部模組能夠進行使用,其中 NgModule 中最重要的屬性為:

  1. declarations: 主要為宣告本模組中擁有的視圖類別,其中有三種視圖類別,分別為元件、指令和管理。
  2. exports: 主要為可以讓此模組用於其它模組的元件當樣板,所以需要宣告匯出。
  3. imports: 主要為需要的宣告元件樣板的類別在其它模組中,所以需要宣告匯入。
  4. providers: 主要為服務的創建者,並且加入全域服務的部份,可以應用於任何部份。
  5. bootstrap: 主要為應用的主視圖,只有根模組才能設定此屬性。

再來當我們了解模組的基本概念之後,開啟 src\app 資料夾中的 app.module.ts 檔案,更進一步了解模組程式碼。我們可以發現一開始匯入除了 NgModule 模組之外,還包括三個輔助模組分別為:

  1. BrowserModule: 主要提供在瀏覽器中執行應用時所需要的關鍵服務和指令。
  2. FormsModule: 主要提供表單處理和雙向綁定等服務和指令。
  3. HttpModule: 主要提供 HTTP 請求和回應的服務。

接著我們還有匯入 AppComponent 和 LoginComponent 的元件,並且針對元件進行宣告,針對輔助模組進行匯入,以及 bootstrap 則設定哪一個視件為引導性的元件,例如: AppComponent,主要會在 DOM 中產生這個引導性元件,並且將結果放進 index.html 中的 app-root 標籤元素中。最後將 AppModule 的物件宣當告為公共,讓外部模組能夠進行使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';

import { AppComponent } from './app.component';
import { LoginComponent } from './login/login.component';

@NgModule({
declarations: [
AppComponent,
LoginComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }

最後我們開啟 src 資料夾中的 main.ts 檔案,更進一步了解 Angular 是如何引導 AppModule 來啟動應用,同時針對不同的作業系統平台,Angular 則提供許多引導的選項,像是預設為 JIT 即時編譯器動態引導適用於開發測試時,或者 AOT 預編譯器靜態引導適用於移動裝置和高延遲網路應用。

1
2
3
4
5
6
7
8
9
10
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { environment } from './environments/environment';
import { AppModule } from './app/app.module';

if (environment.production) {
enableProdMode();
}

platformBrowserDynamic().bootstrapModule(AppModule);

相關資源