Structural Directive 主要用來操作 DOM Tree,新增、刪除 DOM 節點,常用指令有 ngFor
、ngIf
、ngSwitch
三種。這些標籤放在 html 當作一種屬性就可以使用了,我們來看看這三種 Structural Directive 的用法。
假設我今天要做一個超連結清單,導到各個頁面,那我可以先在 ts
中放一個陣列,來記錄這些頁面的名字:
// homepage.component.ts
links = [
{
id: 1,
name: 'HOME'
},
{
id: 2,
name: 'ABOUT US'
},
{
id: 3,
name: 'Students'
},
{
id: 4,
name: 'Teachers'
}
];
接下來,我們到 homepage.component.html
,新增我們的超連結:
// homepage.component.html
<a *ngFor="let link of links" [href]="'#' + link.name">
{{link.name}}
</a>
ngFor可以包一個迭代語法,*ngFor="let link of links"
,意思是:宣告一個變數 link
,然後 link
會遍歷 links
中的每個元素。links
就是我們剛剛放在 ts
中的陣列,所以第一個 link
變數,會長這個樣子:
{
id: 1,
name: 'HOME'
},
後面以此類推。
href
我們就先設定成 '#' + link.name
,記得要加上[ ]
,做 Property Binding。
我們來看看效果:
就會依照我的 links
陣列,產生四個連結。請原諒他長得很醜。
Structural Directive 的前面會有一個 「*
」,這是一個語法糖,他會做以下的事,我們借一下官方的範例。
我們通常會寫這樣的語法:
<div *ngIf="hero" class="name">{{hero.name}}</div>
而「*
」這個語法糖會將程式碼拆成這樣,用 ng-template
將元件包起來,稍微知道即可:
<ng-template [ngIf]="hero">
<div class="name">{{hero.name}}</div>
</ng-template>
那麼如果我只想顯示特定元素呢?我可以用 ngIf
讓一些元素不要顯示,ngIf
在 ""
內放一個判斷式,當判斷式為 True
時就會建立 DOM。
我們試著過濾掉 id < 3
的元素 :
// homepage.component.html
<div *ngFor="let link of links">
<a *ngIf="link.id < 3" [href]="'#' + link.name">
{{ link.name }}
</a>
</div>
結果:Students
跟 Teachers
由於 id >= 3 ,所以不會被建立。
但是因為我在 <a></a>
包了一層 <div></div>
,所以我的連結並不在同一列。
那怎麼辦呢,你可能會想這樣做:
<a *ngFor="let link of links" *ngIf="link.id < 3"
[href]="'#' + link.name">
{{ link.name }}
</a>
但是 Angular 不允許我們在同一個 html 標籤下,使用兩個 Structural Directive,所以這樣寫是行不通的。這時候就需要用到 ng-container
,把其中一個 Directive 裝起來:
// homepage.component.html
<ng-container *ngFor="let link of links">
<a *ngIf="link.id < 3" [href]="'#' + link.name">
{{ link.name }}
</a>
</ng-container>
結果 :
這樣就不需多包一層 html 元素。
ngSwitch 其實是一組共三個 Directive,會一起使用:
如果有寫過 C/C++ 或 java 的經驗,你應該寫過這種程式碼:
int i;
...
switch (i){
case 0:
...
break;
case 1:
...
break;
...
...
default:
...
}
那麼以上面這段程式碼來看,就是 switch
會接一個變數 i
,當 i = 0
就做 case 0
裡面的事情,i = 1
就做 case 1
裡面的事情,若都沒有條件符合,就做 default
的事。也就是多條支路,只會選擇一條。ngSwitch
就像上面的 switch
,ngSwitchCase
像 case
,ngSwitchDefault
像 default
。
而 ngSwitch
其實是 Attribute Directive
,所以用法上不須加上「*
」。
現在我想讓我的清單的字,依照 name
來套用各種顏色,我就可以利用 ngSwitch
這麼做:
// homepage.component.html
<ng-container *ngFor="let link of links">
<div [ngSwitch]="link?.name">
<div *ngSwitchCase="'HOME'" style="color: blue">{{link?.name}}</div>
<div *ngSwitchCase="'ABOUT US'" style="color:red">{{link?.name}}</div>
<div *ngSwitchCase="'Students'" style="color: green">{{link?.name}}</div>
<div *ngSwitchCase="'Teachers'" style="color:violet">{{link?.name}}</div>
<div *ngSwitchDefault>output2</div>
</div>
</ng-container>
ngSwitch
用 Property Binding 傳入變數 link?.name
,這個問號的語法,是當你傳入變數時,會自動檢查變數是不是 Null
,也就是空值。如果是空值,就不會去存取 link.name
,避免錯誤。
*ngSwitchCase
的地方,放的是要選擇的條件,這邊是 link.name
,要記得用單引號將字串 HOME
括號起來。然後我對不同的 name
套用不同的 style="color: xxx"
,就可以改變字的顏色。
因為我沒有設定 link.name
為 Teachers 的 case
,所以Teachers 這個元素會選擇 ngSwitchDefault
這個支路。
我們來看一下效果:
就可以看到字體顏色依照我們所設定的改變了。
明天我們繼續介紹 Directive 的第三部曲 Attribute Directive。