---
# System prepended metadata

title: Angular WorkShop - 1

---

Angular WorkShop - 1
===

## Angular 9 開發環境說明

https://gist.github.com/doggy8088/15e434b43992cf25a78700438743774a

### 安裝 VSCODE 
https://code.visualstudio.com/
* 安裝 Angular Extension Pack 擴充套件 (Will)
* 安裝 Prettier - Code formatter 擴充套件
### 安裝 Node.js 
https://nodejs.org/
```
node -v 
```
```
npm -v
```
### 安裝 Angular CLI 工具 
```
npm install -g @angular/cli
```
```
ng version
```
```
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
```

### 驗證 Angular CLI 執行 
* 開啟「命令提示字元」視窗 (Windows) 或 Terminal 應用程式 (Mac OS X)

* cd到自己想建立angular專案的資料夾
* 建立 demo1 專案資料夾與 Angular 專案骨架，請執行下列指令：
    ```
    ng new demo1
    ```
    這個過程會建立 Angular 專案檔案並自動安裝所有 npm 相依套件
* 進入 demo1 目錄 ```cd demo1```
* 啟動 Angular 開發伺服器
    ```
    ng serve
    ```
    http://localhost:4200/


![](https://i.imgur.com/C0xizJh.jpg)



## 認識 TypeScript 與 ES6 重要特性

* JavaScript 是實作 ECMASCript 規範的語言 
* ES6 為了 因應大型或複雜應用程式的需求 而生
* TypeScript 是 Google 發展的，是 JavaScript 的超集合

![](https://i.imgur.com/tKcLkTY.png)

### Angular 開發時會看到的語法

* 宣告變數的新關鍵字 let 和 const
* 箭頭函式
* classes 的創建
* 引數的預設值

### Declaration - let & const

解決 ```var``` hoisting(提升) 問題

> hoisting - 變數宣告會被隱含提升到其所在區域內的頂端

![](https://i.imgur.com/iCWKeoi.png)

在執行時期時，所有var變數都會自動被hoisting。

因此若程式中有參考到未用var定義過的變數時，

會變成undefined，不會產生ERROR，

容易在DEBUG時造成誤解。

#### 用 let 取代 var

![](https://i.imgur.com/2LKe4hX.png)

使用let不會被hoisting，它是依附在{}的區塊中，

若程式中有參考到未用let定義過的變數時，

會產生ERROR，此行為比較接近常用的程式語言寫法。

#### 使用const定義常數值

不好的寫法

![](https://i.imgur.com/gyCWn6p.png)

改用const會讓程式可容易閱讀

![](https://i.imgur.com/zGrPjUD.png)

const也不會有hoisting的問題

### function

#### arrow function

arrow function ()=>

寫法如下

```javascript=
fnName(x,y) => {
	//...
}
```

傳統寫法與ES6寫法的比較

```javascript=
//ES5
function foo(x, y) { 
    x++;
    y--;
    return x + y;
}

//ES6
foo(x, y) => {
    x++; 
    y--; 
    return x+y;
}
```
##### arrow function解決了this指向的問題

此範例中的this，

因為被settimeout callback function影響的關係，

this變成指向window.this。

```javascript=
//沒有使用arrow function

class Animal {
    constructor(){
        this.type = 'animal'
    }
    says(say){
        setTimeout(function(){
            console.log(this.type + ' says ' + say)
        }, 1000)
    }
}

 var animal = new Animal()
 animal.says('hi')  //undefined says hi
```

用了()=>之後，函數體內的this，

【就是定義時所在的對象】，而不是使用時所在的對象。

()=>不會有自己的this，它的this是繼承外面的，

因此內部的this就是外層代碼區域的this。

```javascript=
class Animal {
    constructor(){
        this.type = 'animal'
    }
    says(say){
        setTimeout( () => {
            console.log(this.type + ' says ' + say)
        }, 1000)
    }
}
 let animal = new Animal()
 animal.says('hi')  //animal says hi
```

#### function defaults

```javascript=
//ES5
function animal(type){
    type = type || 'cat'  
    console.log(type)
}
animal();

//ES6
animal => (type = 'cat'){
    console.log(type)
}
animal();
```

### Objects, Strings, and Object.assign

既有型別或物件的擴充

#### 型別擴充 Object

更簡潔的屬性宣告。

ES6允許只寫屬性名稱，

屬性值為【屬性名稱所代表的變數值】

```javascript=
//ES5
function f1(x,y){
	return {x:x,y:y};
}

//ES6
function f2(x,y){
	return {x,y};
}

console.log(f1(1,2)); // Object {x:1,y:2}
console.log(f2(1,2)); // Object {x:1,y:2}
```

#### 型別擴充 String

字串樣板(template literals)：加入標籤自定義字串樣板

* 樣板起始符：`` (兩個反折號)
* 不需要加上 \n 就可以完成字串的多行拼接

```javascript=
//ES5 
var multilineText = (
	"foo\n" + 
	"bar\n"
);

//ES6 
var multilineText = (
	`foo 
	 bar`
);
```

${expression} 可在字串模版內，使用變數及函式

![](https://i.imgur.com/IR97PpU.png)

#### Object.assign

為了讓Function在各種不同應用程式可以重複使用，

會使用【options object】做function的參數傳入，

而不是用個別的具名參數。

##### 使用Object.assign

做option object的初值及傳入值的合併。

![](https://i.imgur.com/F5Vodj7.png)

Object.assign若有指定多個Source Object，

且有相同的properties時，會讓"後"值蓋"前"值。

![](https://i.imgur.com/vociddx.png)

#### Arrays

ES6提供更多操作Array的技巧

##### Array Destructuring

可以將陣列或物件中的資料取出成獨立變數。

![](https://i.imgur.com/fMr6eHn.png)

##### Combining Destructuring With Rest Params

![](https://i.imgur.com/z2dqj5M.png)

##### Using 【for…of】 to Loop Over Arrays

![](https://i.imgur.com/MjDJngI.png)

##### Array.find

回傳第一個滿足所提供之測試函式的元素值。

否則回傳 undefined。

![](https://i.imgur.com/XjfeSlq.png)

#### Classes

傳統的寫法

![](https://i.imgur.com/IvcaBNK.png)

使用Class語法

![](https://i.imgur.com/fRxgeJ9.png)

##### Class Inheritance

如同Java一樣使用extends來寫子類別

![](https://i.imgur.com/rIBHOWu.png)

在子類別中覆寫方法

![](https://i.imgur.com/NzOA76L.png)

在ES6之前，要做到JavaScript的OOP寫法，

必需要懂得如何使用prototype

但ES6之後，你可以像寫Java一樣寫JavaScript。

#### Modules

傳統的做法：所有Libary都被加到全域變數

* 容易造成全域變數汙染。
* 增加很多Side Effects，變數命名常常造成衝突。

![](https://i.imgur.com/3YFQsJE.png)

使用模組來減少全域變數汙染的情形，

* 利用export語法將variable或是function公開，
* 利用import…from語法，引用module。

![](https://i.imgur.com/SFCxEGX.png)


![](https://i.imgur.com/ZiRbIlm.jpg)

## 體驗 Angular 開發流程

終極目標：理解與完成 angular.tw 你的第一個應用

https://angular.tw/start

### Angular的應用程式組成

![](https://i.imgur.com/Pe5OCGh.png)

### Angular元件的基本構成

![](https://i.imgur.com/hUytrc6.png)

### 快速體驗一個 Angular 專案

#### App Component 根元件

app.component.ts

```typescript

// 載入會用到的模組，angular/core 是 Angular 核心套件模組
import { Component } from '@angular/core';

@Component({
  selector: 'app-root', // 根元件在html對應的tag名稱
  templateUrl: './app.component.html', //根元件的html模版
  styleUrls: ['./app.component.scss'] //根元件的css樣式
})
export class AppComponent {
  title = 'demo1';
}

```
#### 在index.html使用根元件
```html
<body>
    <app-root></app-root>
</body>
```

#### 增加資料Binding

```html
<span>{{ title }} app is {{action}}!</span>
```

```typescript=
export class AppComponent {
  title = 'everrich';
  action = 'showing';
}
```

#### 建立子元件類別

* 在 terminal 輸入 angular cli 的語法就可以自動產生

```ng generate component header```
```ng g c header```

https://angular.tw/cli/generate

![](https://i.imgur.com/6NYOi6V.png)

#### 在根元件中使用子元件

* 修改 app.component.ts的template 讓根元件認識要參考的子元件

```html
<app-header></app-header>

<!-- Toolbar -->
<div class="toolbar" role="banner">
...
</div>
```

![](https://i.imgur.com/NPYAxRj.png)


* 把 header 的 template html 從 根元件搬到子元件

![](https://i.imgur.com/9NNJ7K9.png)

![](https://i.imgur.com/zP5OsTj.png)

* 把 header 的 style 從 根元件搬到子元件

![](https://i.imgur.com/Ru6fcAI.png)

![](https://i.imgur.com/egm9kO1.png)

### Data Binding 介紹

#### Data Binding - Interpolation

```
{{ expression }} 
```

![](https://i.imgur.com/Wv85RWJ.png)

![](https://i.imgur.com/oANt2ER.png)

#### Data Binding - Property Binding

```
[property] = 變數
```

![](https://i.imgur.com/Pj2qLY3.png)


#### Data Binding - Event Binding

```
(event) = your-custom-fn
```

![](https://i.imgur.com/dtps8qy.png)

![](https://i.imgur.com/QdBFbd7.png)

#### Data Binding - TwoWay Binding

```
[(ngModel)] = 變數
```

* 使用 ngModel 前一定要先注意 是否有加入 FormsModule

```
// in app.module.ts

import { FormsModule } from '@angular/forms';
```

* 在 header.component.html 加上一個 input

```html
  <span (click)="alertGreeting()">{{headerGreeting}}</span>
*  <div class="spacer"></div>
  <!-- ↓↓↓ add input and bind ngModel here ↓↓↓  -->
  <input type="text" [(ngModel)]="headerGreeting"/>
```

![](https://i.imgur.com/YUU4jPC.png)

此時修改 input 裡面的值，span 的 內容也會跟著變化 

### STRUCTURAL DIRECTIVES

#### ngFor

* 用來循環顯示Collection的資料

* 語法：```*ngFor="let item of collection"```

* 調整 app.component.html 拿掉 前置的ICON

* 調整 app.component.ts 新增 resources 陣列變數

![](https://i.imgur.com/svSrRnC.png)

* 修改 app.component.html 使用 ngFor

```html
  <div class="card-container">
    <a class="card" target="_blank" rel="noopener"
      [href]="r.link" *ngFor="let r of resources">
      <span>{{r.title}}</span>
      <svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg>
    </a>
  </div>
```

* 用 ```ng-container``` 幫我們整理 template 的語法 

```html
  <div class="card-container">
    <ng-container  *ngFor="let r of resources">
      <a class="card" target="_blank" rel="noopener" [href]="r.link">
        <span>{{r.title}}</span>
        <svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg>
      </a>
    </ng-container>
  </div>
```

##### ngFor use local variable

```
*ngFor="let idx = index ; let item of collection"
```

![](https://i.imgur.com/VF27W89.png)

* 修改 app.component.html 加上 index

```
  <div class="card-container">
    <ng-container  *ngFor="let r of resources; let idx = index;">
      <a class="card" target="_blank" rel="noopener" [href]="r.link">
        <span>{{idx + 1}}.{{r.title}}</span>
        <svg class="material-icons" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/></svg>
      </a>
    </ng-container>
  </div>
```
 
#### ngIf

* 用來判斷是否顯示，語法 ```*ngIf="布林變數值"```

* 修改 app.component.html 使用 ngIf

```
<p *ngIf="idx === 0">Resource Start Here</p>
```

## Q & A






