iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 11
0
Modern Web

從零開始的Angular前端開發系列 第 11

# DAY 11 Directive - Structural Directive

Structural Directive 主要用來操作 DOM Tree,新增、刪除 DOM 節點,常用指令有 ngForngIfngSwitch 三種。這些標籤放在 html 當作一種屬性就可以使用了,我們來看看這三種 Structural Directive 的用法。

ngFor

假設我今天要做一個超連結清單,導到各個頁面,那我可以先在 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}}&nbsp;
</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 讓一些元素不要顯示,ngIf"" 內放一個判斷式,當判斷式為 True 時就會建立 DOM。

我們試著過濾掉 id < 3 的元素 :

// homepage.component.html

<div *ngFor="let link of links">
  <a *ngIf="link.id < 3" [href]="'#' + link.name">
    {{ link.name }}&nbsp;
  </a>
</div>

結果:

StudentsTeachers 由於 id >= 3 ,所以不會被建立。
但是因為我在 <a></a> 包了一層 <div></div>,所以我的連結並不在同一列。
那怎麼辦呢,你可能會想這樣做:

  <a *ngFor="let link of links" *ngIf="link.id < 3" 
      [href]="'#' + link.name">
    {{ link.name }}&nbsp;
  </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>
  &nbsp;
</ng-container>

結果 :

這樣就不需多包一層 html 元素。

ngSwitch

ngSwitch 其實是一組共三個 Directive,會一起使用:

  • ngSwitch
  • ngSwitchCase
  • ngSwitchDefault

如果有寫過 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 就像上面的 switchngSwitchCasecasengSwitchDefaultdefault

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


上一篇
# DAY 10 Directive - Component
下一篇
# DAY 12 Directive - Attribute directives
系列文
從零開始的Angular前端開發30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言