.NET Magazine國際中文電子雜誌
作 者:許薰尹
審 稿:張智凱
文章編號: N190520701
出刊日期: 2019/5/1
在這篇文章中,將要介紹如何利用Angular CLI(Command Line Interface)工具程式建立Angular 7 專案,安裝Angular CLI開發環境,以及介紹一個Angular專案的檔案結構與項目,以讓你了解如何透過Angular來開發前端網頁程式的準備與基本入門。
安裝Angular CLI(Command Line Interface)工具程式
首先開發環境之中要先安裝Angular CLI(Command Line Interface)工具程式,此程式可以協助我們建立一個Angular 7 專案,以方便進行開發的動作。若要安裝Angular CLI(Command Line Interface)工具程式,可以透過「npm」工具程式來進行下載。「npm」工具程式隨著Node.js散發,也就是說只要安裝「Node.js」就會自動安裝「npm」工具程式。你可以由Node.js官網(https://nodejs.org/en/)下載並安裝「Node.js」。「Node.js」安裝完成之後,可以在命令提示字元輸入以下「npm install」指令來安裝Angular CLI(Command Line Interface)工具程式,其中的「-g」參數表示要安裝成全域套件:
npm install -g @angular/cli
完成之後便可以利用「ng」 來執行命令。
建立專案
接下來我們來了解如何建立專案。首先在命令提示字元輸入以下指令,建立專案程式要存放的資料夾,例如以下範例將放在「agDemo」資料夾中:
mkdir agDemo
在命令提示字元輸入以下指令,切換到目前工作路徑到「agDemo」資料夾:
cd agDemo
在命令提示字元輸入以下指令,使用「ng new」建立一個名為「agWeb」專案:
ng new agWeb
接著命令提示字元會提示是否加入路由與CSS使用的格式,目前只要按下「Enter」鍵接收預設值便可,然後需要稍待一下,建立專案需要花費一段時間下載相關套件,執行的結果如下圖所示:

圖 1:建立新專案。
在命令提示字元輸入以下指令,切換到目前工作路徑到「agWeb」資料夾:
cd agWeb
在命令提示字元輸入以下指令:
ng serve
這個指令會編譯目前的專案,並且啟動網站伺服器,預設伺服器會接聽在「4200」埠,執行的結果請參考下圖所示:

圖 2:編譯專案,並且啟動網站伺服器。
若想要在編譯專案,啟動網站伺服器之後,能順便開啟瀏覽器帶出網站首頁,則可以使用參數「-o」:
ng serve –o
這個範例程式的執行結果參考如下:

圖 3:啟動範例網站。
Angular專案
我們來檢視一下新建立的Angular專案包含的檔案與檔案結構:
l 「e2e」資料夾:端對端(End-To-End)測試資料夾,通常用於整合測試(Intergration Testing)。
l 「e2e/protractor.conf.js」檔案:Protractor單元測試組態檔案。
l 「node_modules」資料夾:npm套件存放地。
l 「src」資料夾:原始程式檔案存放地。
l 「src/karma.conf.js」檔案:用於Protractor單元測試框架。
l 「editorconfig」檔案:用來設定規則,限定程式設計風格的一致性,例如設定空白要兩格、或四格的規則,提供工具檢查或排版的依據。
l 「angular.json」檔案:設定專案名稱、版本等專案相關資訊。
l 「gitignore 」檔案:設定不放到Git Repository(版本庫、套件庫)的檔案。
l 「assets」資料夾:可用來存放圖片檔案、JavaScript程式檔案。
l 「environments」資料夾:用於開發環境與生產環境(Production)的編譯設定,包含兩個檔案:「environment.prod.ts」與「environment.ts」。
l 「favicon.ico」檔案:預設的網站圖示檔。
l 「styles.css」檔案:用於加入全域樣式。
l 「test.ts」檔案:包含單元測試程式碼。
l 「tsconfig.app.json」檔案:儲存編譯階段的組態設定。
l 「typings.d.ts」檔案:TypeScript定義檔。
l 「main.ts」檔案:專案的進入點,預設匯入angular核心模組「@angular/core」與「@angular/platform-browser-dynamic」、專案中的「./app/app.module」與「./environments/environment」。
目前「main.ts」檔案程式的內容看起來如下:
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';
if (environment.production) {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.error(err));
當「platformBrowserDynamic().bootstrapModule(AppModule)」這行程式在瀏覽器執行時,會將「index.html」檔案載入,然後執行AppModule(app.module.ts),AppModule又叫用AppComponent。
l 「index.html」檔案:定義網站首頁的HTML結構。目前「index.html」檔案的內容參考如下:
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>AgWeb</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>
<body>標籤中的<app-root></app-root>對應到「app.component.ts」檔案中的「selector」,並插入元件「app.component.html」的執行結果。
l 「polyfills.ts」檔案:用於產生向下相容的JavaScript程式碼。
l 「package.json」檔案:記錄專案安裝的套件與開發相依套件、套件版本等資訊。目前「package.json」檔案的內容參考如下:
package.json
{
"name": "ag-web",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"@angular/animations": "~7.2.0",
"@angular/common": "~7.2.0",
"@angular/compiler": "~7.2.0",
"@angular/core": "~7.2.0",
"@angular/forms": "~7.2.0",
"@angular/platform-browser": "~7.2.0",
"@angular/platform-browser-dynamic": "~7.2.0",
"@angular/router": "~7.2.0",
"core-js": "^2.5.4",
"rxjs": "~6.3.3",
"tslib": "^1.9.0",
"zone.js": "~0.8.26"
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.13.0",
"@angular/cli": "~7.3.1",
"@angular/compiler-cli": "~7.2.0",
"@angular/language-service": "~7.2.0",
"@types/node": "~8.9.4",
"@types/jasmine": "~2.8.8",
"@types/jasminewd2": "~2.0.3",
"codelyzer": "~4.5.0",
"jasmine-core": "~2.99.1",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~3.1.1",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "~2.0.1",
"karma-jasmine": "~1.1.2",
"karma-jasmine-html-reporter": "^0.2.2",
"protractor": "~5.4.0",
"ts-node": "~7.0.0",
"tslint": "~5.11.0",
"typescript": "~3.2.2"
}
}
l 「tsconfig.json」檔案:「用來指定TypeScript程式編譯的選項,以便於引導編譯器編譯程式碼。目前「tsconfig.json」檔案的內容參考如下:
tsconfig.json
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"module": "es2015",
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"importHelpers": true,
"target": "es5",
"typeRoots": [
"node_modules/@types"
],
"lib": [
"es2018",
"dom"
]
}
}
l 「tslint.json」檔案:編譯規則設定檔案。
l 「src/app/app.module.ts」檔案:預設檔案內容如下,其中包含匯入一些外部程式庫的程式碼:
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule,
AppRoutingModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Angular中的模組(Module)用來將相關的元件(Component)、指示詞(Directive)、服務(Service)群組在一起。你可以利用「@NgModule」來定義模組。模組中需要使用「import」關鍵字匯入「@angular/core」。
模組中的「declarations」屬性的值是一個陣列,其中包含了「AppComponent」元件,此元件是專案建立時,設定的預設元件。「imports」屬性的值是一個陣列,設定要匯入的其它模組,預設包含「BrowserModule」、「AppRoutingModule」模組。「providers」屬性用來設定要使用的服務(Service);「bootstrap」屬性設定程式啟動時預設要建立的元件。
元件(Component)
元件(Component)是Angular 應用程式的基本單位,元件包含三個重要的檔案:「app.component.css」、「app.component.html」與「app.component.ts」檔案。其中「app.component.css」檔案:用來加入元件的CSS樣式;「app.component.html」檔案用來加入元件的HTML結構,目前檔案內容如下:
app.component.html
<!--The content below is only a placeholder and can be replaced.-->
<div style="text-align:center">
<h1>
Welcome to {{ title }}!
</h1>
<img width="300" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz=略">
</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://angular.io/cli">CLI Documentation</a></h2>
</li>
<li>
<h2><a target="_blank" rel="noopener" href="https://blog.angular.io/">Angular blog</a></h2>
</li>
</ul>
「app.component.ts」檔案:用來加入元件的處理邏輯,毋庸置疑「app.component.ts」檔案就是撰寫元件的核心,目前檔案的內容如下:
app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'agWeb';
}
讓我們針對目前程式碼做些小小的修改,程式改寫如下,將網站的標題(title)改為「MyWeb」:
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'MyWeb';
}
接著修改「app.component.css」檔案中的程式碼,加入自訂樣式:
.main {
background-color: honeydew;
}
修改「app.component.html」檔案中的程式碼,定義元件的HTML標籤,利用{{}}資料繫結(Data Binding)語法來顯示「AppComponent」元件「title」屬性中設定的網站標題,而{{ title }} 的值是由「app.component.ts」檔案中的程式來進行初始化。:
<div class="main">
<div style="text-align:center">
<h1>
Welcome to {{ title }}!
</h1>
</div>
</div>
若先前使用參數「-o」來編譯專案、啟動網站伺服器,與開啟瀏覽器帶出網站首頁:
ng serve –o
則只需要切換到瀏覽器,修改過的網站首頁的內容會自動更新顯示在瀏覽器中。這個範例程式的執行結果參考如下:

圖 4:網站執行結果。
除了前文提及的「app.component.css」、「app.component.html」與「app.component.ts」三個檔案之外,元件還包含「app.component.spec.ts」檔案,其中包含了元件的單元測試程式碼,目前的程式看起來如下:
app.component.spec.ts
import { TestBed, async } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
RouterTestingModule
],
declarations: [
AppComponent
],
}).compileComponents();
}));
it('should create the app', () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
});
it(`should have as title 'agWeb'`, () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('agWeb');
});
it('should render title in a h1 tag', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('Welcome to agWeb!');
});
});
自訂元件
Angular的開發都是繞著元件打轉,我們可以利用Angular CLI(Command Line Interface)工具程式來自訂自己的元件。例如切換到命令提示字元,在專案根目錄,輸入以下指令,建立一個「contact」元件,來顯示資料:
ng generate component contact
這個命令執行結果,請參考下圖所示:

圖 5:建立「contact」元件。
此外你也可以利用簡短的命令來加快設計的速度,上述的命令可以改寫為:
ng g c contact
新建立的元件相關檔案會置放於「.\src\app\ contact」資料夾之中,請參考下圖所示:

圖 6:元件檔案結構。
目前「contact.component.html」檔案包含的程式如下,使用HTML標籤顯示一個文字字串:
contact.component.html
<p>
contact works!
</p>
而「contact.component.ts」檔案包含的程式如下:
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-contact',
templateUrl: './contact.component.html',
styleUrls: ['./contact.component.css']
})
export class ContactComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
檢視「app.module.ts」檔案,會自動加入「import」指令匯入「contact」元件的程式碼:
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ContactComponent } from './contact/contact.component';
@NgModule({
declarations: [
AppComponent,
ContactComponent
],
imports: [
BrowserModule,
AppRoutingModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
客製化首頁
讓我們來修改一下程式碼,讓網站首頁直接顯示出「contact」元件的資訊。修改「app.module.ts」檔案,將「bootstrap」屬性設定成「ContactComponent」:
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ContactComponent } from './contact/contact.component';
@NgModule({
declarations: [
AppComponent,
ContactComponent
],
imports: [
BrowserModule,
AppRoutingModule
],
providers: [],
bootstrap: [ContactComponent]
})
export class AppModule { }
修改「index.html」檔案,將<body>之中的標籤修改如下:
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>AgWeb</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-contact></app-contact>
</body>
</html>
切換到瀏覽器,網站首頁將顯示「contact」元件的內容:

圖 7:修改首頁程式執行結果。
使用資料繫結語法
讓我們來加入連絡人資訊,修改「contact.component.ts」檔案中的程式,在「ContactComponent」類別之中宣告三個屬性,分別紀錄「email」、「address」、「phone」資訊:
contact.component.ts
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-contact',
templateUrl: './contact.component.html',
styleUrls: ['./contact.component.css']
})
export class ContactComponent implements OnInit {
email: string = 'Support@example.com';
address: string = "One UCOM Way";
phone: string = "123456789";
constructor() { }
ngOnInit() {
}
}
接著修改「contact.component.html」檔案,使用資料繫結語法,將資料呈現出來:
contact.component.html
<p>
contact Info
</p>
<address>
{{address}} <br />
</address>
Phone : <a href="tel:{{phone}}">{{phone}}</a>
<address>
<strong>Support:</strong> <a href="mailto:{{email}}">{{email}}</a><br />
</address>
切換到瀏覽器,網站首頁將顯示「contact」元件的內容:

圖 8:使用資料繫結語法呈現連絡人資訊。